From 6593e25f41c8c75cc84fb862340244498fe9aec1 Mon Sep 17 00:00:00 2001 From: Rob Bairos Date: Mon, 5 Apr 2021 08:42:39 -0400 Subject: [PATCH 01/17] MovieCart Streaming image and audio content created by presenting dynamic 1K of data on the bus, with On Screen Display. Volume, Brightness and Shuttle controlled by joystick and console switches. Original implementation: github.com/lodefmode/moviecart --- src/emucore/Bankswitch.cxx | 3 + src/emucore/Bankswitch.hxx | 4 +- src/emucore/CartCreator.cxx | 5 + src/emucore/CartDetector.cxx | 11 + src/emucore/CartDetector.hxx | 5 + src/emucore/CartMVC.cxx | 84 ++++ src/emucore/CartMVC.hxx | 181 +++++++ src/emucore/MovieCart/KernelData.hxx | 421 +++++++++++++++++ src/emucore/MovieCart/MovieCart.cxx | 626 +++++++++++++++++++++++++ src/emucore/MovieCart/MovieCart.hxx | 147 ++++++ src/emucore/MovieCart/MovieInputs.hxx | 91 ++++ src/emucore/MovieCart/StreamReader.cxx | 96 ++++ src/emucore/MovieCart/StreamReader.hxx | 135 ++++++ src/windows/Stella.vcxproj | 8 + src/windows/Stella.vcxproj.filters | 24 + 15 files changed, 1839 insertions(+), 2 deletions(-) create mode 100755 src/emucore/CartMVC.cxx create mode 100755 src/emucore/CartMVC.hxx create mode 100755 src/emucore/MovieCart/KernelData.hxx create mode 100755 src/emucore/MovieCart/MovieCart.cxx create mode 100755 src/emucore/MovieCart/MovieCart.hxx create mode 100755 src/emucore/MovieCart/MovieInputs.hxx create mode 100755 src/emucore/MovieCart/StreamReader.cxx create mode 100755 src/emucore/MovieCart/StreamReader.hxx diff --git a/src/emucore/Bankswitch.cxx b/src/emucore/Bankswitch.cxx index ba1f855a7..ce3fa69d9 100644 --- a/src/emucore/Bankswitch.cxx +++ b/src/emucore/Bankswitch.cxx @@ -140,6 +140,7 @@ Bankswitch::BSList = {{ { "FC" , "FC (32K Amiga)" }, { "FE" , "FE (8K Decathlon)" }, { "MDM" , "MDM (Menu Driven Megacart)" }, + { "MVC" , "MVC (Movie Cart)" }, { "SB" , "SB (128-256K SUPERbank)" }, { "TVBOY" , "TV Boy (512K)" }, { "UA" , "UA (8K UA Ltd.)" }, @@ -226,6 +227,7 @@ Bankswitch::ExtensionMap Bankswitch::ourExtensions = { { "FC" , Bankswitch::Type::_FC }, { "FE" , Bankswitch::Type::_FE }, { "MDM" , Bankswitch::Type::_MDM }, + { "MVC" , Bankswitch::Type::_MVC }, { "SB" , Bankswitch::Type::_SB }, { "TVB" , Bankswitch::Type::_TVBOY }, { "TVBOY" , Bankswitch::Type::_TVBOY }, @@ -284,6 +286,7 @@ Bankswitch::NameToTypeMap Bankswitch::ourNameToTypes = { { "FC" , Bankswitch::Type::_FC }, { "FE" , Bankswitch::Type::_FE }, { "MDM" , Bankswitch::Type::_MDM }, + { "MVC" , Bankswitch::Type::_MVC }, { "SB" , Bankswitch::Type::_SB }, { "TVBOY" , Bankswitch::Type::_TVBOY }, { "UA" , Bankswitch::Type::_UA }, diff --git a/src/emucore/Bankswitch.hxx b/src/emucore/Bankswitch.hxx index 3c1b2454a..2070ace36 100644 --- a/src/emucore/Bankswitch.hxx +++ b/src/emucore/Bankswitch.hxx @@ -44,8 +44,8 @@ class Bankswitch _CDF, _CM, _CTY, _CV, _DF, _DFSC, _DPC, _DPCP, _E0, _E7, _E78K, _EF, _EFSC, _F0, _F4, _F4SC, _F6, _F6SC, _F8, _F8SC, _FA, - _FA2, _FC, _FE, _MDM, _SB, _TVBOY, _UA, - _UASW, _WD, _WDSW, _X07, + _FA2, _FC, _FE, _MDM, _MVC, _SB, _TVBOY, + _UA, _UASW, _WD, _WDSW, _X07, #ifdef CUSTOM_ARM _CUSTOM, #endif diff --git a/src/emucore/CartCreator.cxx b/src/emucore/CartCreator.cxx index f792b449c..71cc118b8 100644 --- a/src/emucore/CartCreator.cxx +++ b/src/emucore/CartCreator.cxx @@ -55,6 +55,7 @@ #include "CartFC.hxx" #include "CartFE.hxx" #include "CartMDM.hxx" +#include "CartMVC.hxx" #include "CartSB.hxx" #include "CartTVBoy.hxx" #include "CartUA.hxx" @@ -197,6 +198,10 @@ unique_ptr CartCreator::create(const FilesystemNode& file, Bankswitch::typeToName(type) + "'"); break; + case Bankswitch::Type::_MVC: + cartridge = make_unique(file.getPath(), size, md5, settings); + break; + default: cartridge = createFromImage(image, size, detectedType, md5, settings); break; diff --git a/src/emucore/CartDetector.cxx b/src/emucore/CartDetector.cxx index 8d4f5f51b..6d5713f2e 100644 --- a/src/emucore/CartDetector.cxx +++ b/src/emucore/CartDetector.cxx @@ -240,6 +240,8 @@ Bankswitch::Type CartDetector::autodetectType(const ByteBuffer& image, size_t si type = Bankswitch::Type::_3EP; else if(isProbablyMDM(image, size)) type = Bankswitch::Type::_MDM; + else if(isProbablyMVC(image, size)) + type = Bankswitch::Type::_MVC; // If we get here and autodetection failed, then we force '4K' if(type == Bankswitch::Type::_AUTO) @@ -689,6 +691,15 @@ bool CartDetector::isProbablyMDM(const ByteBuffer& image, size_t size) return searchForBytes(image, std::min(size, 8_KB), mdmc, 4); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool CartDetector::isProbablyMVC(const ByteBuffer& image, size_t size) +{ + // MVC version 0, frame 0 + uInt8 sig[] = { 'M', 'V', 'C', 0 }; + return searchForBytes(image, std::min(size, 5), sig, 4); +} + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool CartDetector::isProbablySB(const ByteBuffer& image, size_t size) { diff --git a/src/emucore/CartDetector.hxx b/src/emucore/CartDetector.hxx index 1ff16fc30..0061b1054 100644 --- a/src/emucore/CartDetector.hxx +++ b/src/emucore/CartDetector.hxx @@ -189,6 +189,11 @@ class CartDetector */ static bool isProbablyMDM(const ByteBuffer& image, size_t size); + /** + Returns true if the image is probably an MVC movie cartridge + */ + static bool isProbablyMVC(const ByteBuffer& image, size_t size); + /** Returns true if the image is probably a SB bankswitching cartridge */ diff --git a/src/emucore/CartMVC.cxx b/src/emucore/CartMVC.cxx new file mode 100755 index 000000000..ab05cd0b1 --- /dev/null +++ b/src/emucore/CartMVC.cxx @@ -0,0 +1,84 @@ +//============================================================================ +// +// SSSS tt lll lll +// SS SS tt ll ll +// SS tttttt eeee ll ll aaaa +// SSSS tt ee ee ll ll aa +// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" +// SS SS tt ee ll ll aa aa +// SSSS ttt eeeee llll llll aaaaa +// +// Copyright (c) 1995-2021 by Bradford W. Mott, Stephen Anthony +// and the Stella Team +// +// See the file "License.txt" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +//============================================================================ + +#include "System.hxx" +#include "CartMVC.hxx" + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +CartridgeMVC::CartridgeMVC(const string& path, size_t size, + const string& md5, const Settings& settings, + size_t bsSize) + : Cartridge(settings, md5) +{ + myPath = path; + + // not used + mySize = 1024; + myImage = make_unique(mySize); +} + + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void CartridgeMVC::install(System& system) +{ + mySystem = &system; + + // Map all of the accesses to call peek and poke + System::PageAccess access(this, System::PageAccessType::READWRITE); + + access.directPeekBase = nullptr; + access.directPokeBase = nullptr; + + for(uInt16 addr = 0x1000; addr < 0x2000; addr += System::PAGE_SIZE) + mySystem->setPageAccess(addr, access); +} + + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void CartridgeMVC::reset() +{ + myMovie.init(myPath); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +const ByteBuffer& CartridgeMVC::getImage(size_t& size) const +{ + // not used + size = mySize; + return myImage; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool CartridgeMVC::patch(uInt16 address, uInt8 value) +{ + myMovie.writeROM(address, value); + return true; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +uInt8 CartridgeMVC::peek(uInt16 address) +{ + myMovie.process(address); + return myMovie.readROM(address); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool CartridgeMVC::poke(uInt16 address, uInt8 value) +{ + return myMovie.process(address); +} + diff --git a/src/emucore/CartMVC.hxx b/src/emucore/CartMVC.hxx new file mode 100755 index 000000000..025940f44 --- /dev/null +++ b/src/emucore/CartMVC.hxx @@ -0,0 +1,181 @@ +//============================================================================ +// +// SSSS tt lll lll +// SS SS tt ll ll +// SS tttttt eeee ll ll aaaa +// SSSS tt ee ee ll ll aa +// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" +// SS SS tt ee ll ll aa aa +// SSSS ttt eeeee llll llll aaaaa +// +// Copyright (c) 1995-2021 by Bradford W. Mott, Stephen Anthony +// and the Stella Team +// +// See the file "License.txt" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +//============================================================================ + +#ifndef CARTRIDGEMVC_HXX +#define CARTRIDGEMVC_HXX + +class System; + +#include "bspf.hxx" +#include "Cart.hxx" +#include "MovieCart/MovieCart.hxx" + +/** + Implementation of MovieCart. + 1K of memory is presented on the bus, but is repeated to fill the 4K image space. + Contents are dynamically altered with streaming image and audio content as specific + 128-byte regions are entered. + Original implementation: github.com/lodefmode/moviecart + + @author Rob Bairos +*/ +class CartridgeMVC : public Cartridge +{ + + public: + /** + Create a new cartridge using the specified image + + @param image Pointer to the ROM image + @param size The size of the ROM image (<= 2048 bytes) + @param md5 The md5sum of the ROM image + @param settings A reference to the various settings (read-only) + @param bsSize The size specified by the bankswitching scheme + */ + CartridgeMVC(const string& path, size_t size, const string& md5, + const Settings& settings, size_t bsSize = 2_KB); + ~CartridgeMVC() override = default; + + /** + Reset device to its power-on state + */ + void reset() override; + + /** + Install cartridge in the specified system. Invoked by the system + when the cartridge is attached to it. + + @param system The system the device should install itself in + */ + void install(System& system) override; + + /** + Access the internal ROM image for this cartridge. + + @param size Set to the size of the internal ROM image data + @return A reference to the internal ROM image data + */ + virtual const ByteBuffer& getImage(size_t& size) const; + + /** + Patch the cartridge ROM. + + @param address The ROM address to patch + @param value The value to place into the address + @return Success or failure of the patch operation + */ + virtual bool patch(uInt16 address, uInt8 value); + + /** + Get the byte at the specified address. + + @return The byte at the specified address + */ + uInt8 peek(uInt16 address) override; + + /** + Change the byte at the specified address to the given value + + @param address The address where the value should be stored + @param value The value to be stored at the address + @return True if the poke changed the device address space, else false + */ + bool poke(uInt16 address, uInt8 value) override; + + /** + Get a descriptor for the device name (used in error checking). + + @return The name of the object + */ + string name() const override { return "CartridgeMVC"; } + + /** + Save the current state of this cart to the given Serializer. + + @param out The Serializer object to use + @return False on any errors, else true + */ + bool save(Serializer& out) const override + { + return false; + } + + /** + Load the current state of this cart from the given Serializer. + + @param in The Serializer object to use + @return False on any errors, else true + */ + bool load(Serializer& in) override + { + return false; + } + + /** + Install pages for the specified bank in the system. + + @param bank The bank that should be installed in the system + @param segment The segment the bank should be using + + @return true, if bank has changed + */ + bool bank(uInt16 bank, uInt16 segment = 0) override + { + return false; + } + + /** + Get the current bank. + + @param address The address to use when querying the bank + */ + uInt16 getBank(uInt16 address = 0) const override + { + return 0; + } + + /** + Query the number of banks supported by the cartridge. + */ + uInt16 romBankCount() const override + { + return 1; + } + + private: + + // Currently not used: + // Pointer to a dynamically allocated ROM image of the cartridge + ByteBuffer myImage{nullptr}; + size_t mySize{0}; + + private: + // Following constructors and assignment operators not supported + CartridgeMVC() = delete; + CartridgeMVC(const CartridgeMVC&) = delete; + CartridgeMVC(CartridgeMVC&&) = delete; + CartridgeMVC& operator=(const CartridgeMVC&) = delete; + CartridgeMVC& operator=(CartridgeMVC&&) = delete; + + private: + + MovieCart myMovie; + string myPath; + +}; + +#endif diff --git a/src/emucore/MovieCart/KernelData.hxx b/src/emucore/MovieCart/KernelData.hxx new file mode 100755 index 000000000..6eae1f952 --- /dev/null +++ b/src/emucore/MovieCart/KernelData.hxx @@ -0,0 +1,421 @@ +//============================================================================ +// +// SSSS tt lll lll +// SS SS tt ll ll +// SS tttttt eeee ll ll aaaa +// SSSS tt ee ee ll ll aa +// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" +// SS SS tt ee ll ll aa aa +// SSSS ttt eeeee llll llll aaaaa +// +// Copyright (c) 1995-2021 by Bradford W. Mott, Stephen Anthony +// and the Stella Team +// +// See the file "License.txt" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +//============================================================================ +// Key kernel positions, automatically generated + +/** + Various kernel, OSD and scale definitions + @author Rob Bairos +*/ + +#pragma once + +#include + +#define TIMECODE_HEIGHT 12 +#define MAX_LEVEL 11 +#define DEFAULT_LEVEL 6 +#define BLANK_LINE_SIZE (28+3+37) // 68 + +#define addr_kernel_48 0x800 +#define addr_transport_buttons 0x880 +#define addr_transport_direction 0x897 +#define addr_right_line 0x94c +#define addr_left_line 0x980 +#define addr_pick_continue 0x9c2 +#define addr_main_start 0xa00 +#define addr_aud_bank_setup 0xa0c +#define addr_tg0 0xa24 +#define addr_title_again 0xa3b +#define addr_end_lines 0xa80 +#define addr_end_lines_audio 0xaa1 +#define addr_set_overscan_size 0xaad +#define addr_set_vblank_size 0xac3 +#define addr_pick_transport 0xacc +#define addr_last_audio 0xacf +#define addr_wait_lines 0xad4 +#define addr_transport_done1 0xae7 +#define addr_draw_title 0xb00 +#define addr_title_loop 0xb50 +#define addr_black_bar 0xb52 +#define addr_animate_bar1 0xb58 +#define addr_animate_bar_again1 0xb5a +#define addr_animate_dex1 0xb65 +#define addr_audio_bank 0xb80 +#define addr_reset_loop 0xbfa + +// scale adjustments, automatically generated +const uint8_t scale0[16] = { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}; /* 0.0000 */ +const uint8_t scale1[16] = { 6, 6, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 9, 9}; /* 0.1667 */ +const uint8_t scale2[16] = { 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10}; /* 0.3333 */ +const uint8_t scale3[16] = { 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11}; /* 0.5000 */ +const uint8_t scale4[16] = { 3, 3, 4, 5, 5, 6, 7, 7, 8, 9, 9, 10, 11, 11, 12, 13}; /* 0.6667 */ +const uint8_t scale5[16] = { 1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 10, 10, 11, 12, 13, 14}; /* 0.8333 */ +const uint8_t scale6[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; /* 1.0000 */ +const uint8_t scale7[16] = { 0, 0, 0, 1, 3, 4, 5, 7, 8, 10, 11, 12, 14, 15, 15, 15}; /* 1.3611 */ +const uint8_t scale8[16] = { 0, 0, 0, 0, 1, 3, 5, 7, 8, 10, 12, 14, 15, 15, 15, 15}; /* 1.7778 */ +const uint8_t scale9[16] = { 0, 0, 0, 0, 0, 2, 4, 6, 9, 11, 13, 15, 15, 15, 15, 15}; /* 2.2500 */ +const uint8_t scale10[16] = { 0, 0, 0, 0, 0, 1, 3, 6, 9, 12, 14, 15, 15, 15, 15, 15}; /* 2.7778 */ +const uint8_t *scales[11] = {scale0, scale1, scale2, scale3, scale4, scale5, scale6, scale7, scale8, scale9, scale10}; + +// lower bit is ignored anyways +const uint8_t shiftBright[16 + MAX_LEVEL - 1] = { 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 15, 15, 15, 15}; + +// Compiled kernel +const unsigned char kernelROM[] = +{ + 133, 2, 185, 50, 248, 133, 27, 185, 62, 248, 133, 28, 185, 74, 248, 133, + 27, 185, 86, 248, 133, 135, 185, 98, 248, 190, 110, 248, 132, 136, 164, 135, + 132, 28, 133, 27, 134, 28, 134, 27, 164, 136, 102, 137, 176, 210, 136, 16, + 207, 96, 0, 1, 1, 1, 0, 0, 48, 48, 50, 53, 56, 48, 249, 129, + 129, 128, 248, 0, 99, 102, 102, 102, 230, 99, 140, 252, 140, 136, 112, 0, + 192, 97, 99, 102, 102, 198, 198, 198, 248, 198, 248, 0, 193, 32, 48, 24, + 24, 25, 24, 24, 24, 24, 126, 0, 249, 97, 97, 97, 97, 249, 0, 0, + 0, 0, 0, 0, 248, 128, 128, 224, 128, 248, 255, 255, 255, 255, 255, 255, + 165, 12, 10, 173, 130, 2, 42, 41, 23, 133, 129, 133, 128, 133, 128, 133, + 128, 133, 128, 133, 128, 234, 96, 173, 128, 2, 74, 74, 74, 133, 129, 133, + 128, 133, 128, 133, 128, 133, 128, 133, 128, 133, 128, 234, 96, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 133, 25, 133, 128, + 134, 32, 134, 33, 169, 243, 133, 27, 169, 207, 133, 28, 169, 251, 133, 27, + 169, 239, 162, 191, 160, 66, 133, 28, 169, 54, 133, 6, 134, 27, 169, 238, + 133, 7, 132, 6, 132, 28, 169, 182, 133, 6, 169, 114, 133, 7, 133, 42, + 162, 0, 162, 0, 169, 0, 162, 128, 133, 25, 134, 32, 134, 33, 169, 231, + 133, 27, 169, 159, 133, 28, 169, 253, 133, 27, 169, 247, 162, 223, 160, 242, + 133, 28, 169, 248, 133, 6, 134, 27, 169, 172, 133, 7, 132, 6, 132, 28, + 169, 216, 133, 6, 169, 98, 133, 7, 169, 0, 162, 0, 162, 0, 162, 0, + 133, 42, 76, 76, 249, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 120, 216, 162, 255, 154, 169, 0, 149, 0, 202, 208, 251, 169, 128, 133, 130, + 169, 251, 133, 131, 169, 1, 133, 37, 133, 38, 169, 3, 133, 4, 133, 5, + 133, 2, 162, 4, 133, 128, 202, 208, 251, 133, 128, 133, 16, 133, 17, 169, + 208, 133, 32, 169, 224, 133, 33, 133, 2, 133, 42, 165, 132, 106, 106, 133, + 6, 133, 7, 169, 85, 133, 137, 32, 0, 251, 176, 239, 169, 0, 133, 9, + 141, 129, 2, 141, 131, 2, 169, 6, 133, 4, 169, 2, 133, 5, 169, 0, + 133, 2, 133, 128, 76, 128, 250, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 133, 25, 169, 0, 133, 27, 133, 28, 133, 27, 133, 28, 133, 128, 133, 128, + 133, 128, 169, 0, 133, 16, 234, 133, 17, 169, 208, 133, 32, 169, 192, 133, + 33, 169, 0, 133, 2, 133, 42, 133, 128, 133, 25, 160, 0, 162, 28, 32, + 212, 250, 169, 2, 133, 0, 162, 3, 32, 212, 250, 169, 0, 133, 0, 169, + 2, 133, 1, 162, 37, 32, 212, 250, 162, 0, 134, 1, 32, 128, 248, 169, + 0, 76, 76, 249, 177, 130, 133, 2, 133, 128, 133, 128, 133, 25, 165, 129, + 240, 5, 198, 129, 173, 128, 20, 200, 202, 208, 233, 96, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 162, 30, 32, 82, 251, 169, 2, 133, 0, 162, 3, 32, 82, 251, 169, 0, + 133, 0, 169, 2, 133, 1, 162, 37, 32, 82, 251, 169, 0, 133, 1, 198, + 132, 165, 132, 133, 133, 160, 255, 162, 30, 32, 88, 251, 162, 54, 32, 82, + 251, 160, 11, 32, 0, 248, 169, 0, 133, 27, 133, 28, 133, 27, 133, 28, + 162, 54, 32, 82, 251, 165, 132, 133, 133, 160, 1, 162, 30, 32, 88, 251, + 56, 96, 169, 0, 133, 133, 160, 0, 132, 134, 24, 165, 133, 101, 134, 133, + 133, 133, 2, 133, 9, 202, 208, 242, 96, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 250, 0, 250, 0, 250, +}; + +// OSD labels + +const uint8_t brightLabelEven[] = +{ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 225, 48, 12, 252, + 6, 140, 231, 96, 0, + 0, 113, 48, 12, 96, + 6, 140, 192, 96, 0, + 0, 225, 49, 15, 96, + 6, 152, 195, 96, 0, + 0, 49, 48, 12, 96, + 6, 140, 231, 96, 0, + 0, 225, 48, 12, 96, +}; + +const uint8_t brightLabelOdd[] = +{ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 7, 252, 126, 99, 0, + 0, 113, 48, 12, 96, + 6, 140, 192, 96, 0, + 0, 97, 49, 12, 96, + 7, 248, 223, 224, 0, + 0, 113, 49, 12, 96, + 6, 156, 195, 96, 0, + 0, 113, 48, 12, 96, + 7, 142, 127, 96, 0, + 0, 0, 0, 0, 0 +}; + +const uint8_t volumeLabelEven[] = +{ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 199, 192, 14, 254, + 113, 112, 99, 112, 0, + 0, 140, 192, 14, 192, + 51, 48, 99, 240, 0, + 0, 28, 192, 15, 254, + 31, 48, 99, 240, 0, + 0, 12, 192, 15, 192, + 30, 112, 119, 176, 0, + 0, 7, 252, 12, 254, +}; + +const uint8_t volumeLabelOdd[] = +{ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 97, 224, 99, 112, 0, + 0, 142, 192, 14, 192, + 51, 112, 99, 112, 0, + 0, 28, 192, 15, 192, + 59, 48, 99, 240, 0, + 0, 28, 192, 15, 192, + 30, 112, 99, 176, 0, + 0, 14, 192, 13, 192, + 14, 224, 62, 48, 0, + 0, 0, 0, 0, 0 +}; + +// Level bars +// 8 rows * 5 columns = 40 + +const uint8_t levelBarsEvenData[] = +{ + /**/ + 0, 0, 0, 0, 0, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 2, 40, 161, 133, 20, + 20, 80, 66, 10, 32, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 0, 0, 0, 0, 0, + /**/ + 0, 0, 0, 0, 0, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 3, 40, 161, 133, 20, + 244, 80, 66, 10, 32, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 0, 0, 0, 0, 0, + /**/ + 0, 0, 0, 0, 0, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 3, 232, 161, 133, 20, + 247, 80, 66, 10, 32, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 0, 0, 0, 0, 0, + /**/ + 0, 0, 0, 0, 0, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 3, 239, 161, 133, 20, + 247, 208, 66, 10, 32, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 0, 0, 0, 0, 0, + /**/ + 0, 0, 0, 0, 0, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 3, 239, 161, 133, 20, + 247, 223, 66, 10, 32, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 0, 0, 0, 0, 0, + /**/ + 0, 0, 0, 0, 0, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 3, 239, 191, 133, 20, + 247, 223, 66, 10, 32, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 0, 0, 0, 0, 0, + /**/ + 0, 0, 0, 0, 0, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 3, 239, 191, 133, 20, + 247, 223, 126, 10, 32, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 0, 0, 0, 0, 0, + /**/ + 0, 0, 0, 0, 0, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 20, + 247, 223, 126, 10, 32, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 0, 0, 0, 0, 0, + /**/ + 0, 0, 0, 0, 0, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 20, + 247, 223, 126, 250, 32, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 0, 0, 0, 0, 0, + /**/ + 0, 0, 0, 0, 0, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 244, + 247, 223, 126, 251, 32, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 0, 0, 0, 0, 0, + /**/ + 0, 0, 0, 0, 0, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 0, 0, 0, 0, 0, + +}; + +const uint8_t levelBarsOddData[] = +{ + /**/ + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 20, 80, 66, 10, 32, + 2, 40, 161, 133, 20, + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + /**/ + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 244, 80, 66, 10, 32, + 3, 40, 161, 133, 20, + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + /**/ + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 247, 80, 66, 10, 32, + 3, 232, 161, 133, 20, + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + /**/ + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 247, 208, 66, 10, 32, + 3, 239, 161, 133, 20, + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + /**/ + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 247, 223, 66, 10, 32, + 3, 239, 161, 133, 20, + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + /**/ + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 247, 223, 66, 10, 32, + 3, 239, 191, 133, 20, + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + /**/ + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 247, 223, 126, 10, 32, + 3, 239, 191, 133, 20, + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + /**/ + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 247, 223, 126, 10, 32, + 3, 239, 191, 253, 20, + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + /**/ + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 247, 223, 126, 250, 32, + 3, 239, 191, 253, 20, + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + /**/ + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 32, + 3, 239, 191, 253, 244, + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + /**/ + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, +}; + diff --git a/src/emucore/MovieCart/MovieCart.cxx b/src/emucore/MovieCart/MovieCart.cxx new file mode 100755 index 000000000..c30b65482 --- /dev/null +++ b/src/emucore/MovieCart/MovieCart.cxx @@ -0,0 +1,626 @@ +//============================================================================ +// +// SSSS tt lll lll +// SS SS tt ll ll +// SS tttttt eeee ll ll aaaa +// SSSS tt ee ee ll ll aa +// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" +// SS SS tt ee ll ll aa aa +// SSSS ttt eeeee llll llll aaaaa +// +// Copyright (c) 1995-2021 by Bradford W. Mott, Stephen Anthony +// and the Stella Team +// +// See the file "License.txt" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +//============================================================================ +// Key kernel positions, automatically generated + +/** + Implementation of MovieCart. + 1K of memory is presented on the bus, but is repeated to fill the 4K image space. + Contents are dynamically altered with streaming image and audio content as specific + 128-byte regions are entered. + Original implementation: github.com/lodefmode/moviecart + + @author Rob Bairos +*/ + +#include +#include "KernelData.hxx" +#include "MovieCart.hxx" + +#define LO_JUMP_BYTE(X) ((X) & 0xff) +#define HI_JUMP_BYTE(X) ((((X) & 0xff00) >> 8) | 0x10) + +#define COLOR_BLUE 0x9A +#define COLOR_WHITE 0x0E + +#define OSD_FRAMES 180 +#define BACK_SECONDS 10 + +#define TITLE_CYCLES 1000000 + +bool +MovieCart::init(const std::string& path) +{ + memcpy(myROM, kernelROM, 1024); + + myTitleCycles = 0; + myTitleState = TitleState::Display; + + myA7 = false; + myA10 = false; + myA10_Count = 0; + + myState = 3; + myPlaying = true; + myOdd = true; + myBufferIndex = false; + myFrameNumber = 1; + + myInputs.init(); + myLastInputs.init(); + mySpeed = 1; + myJoyRepeat = 0; + myDirectionValue = 0; + myButtonsValue = 0; + + myLines = 0; + myForceColor = 0; + myDrawLevelBars = 0; + myDrawTimeCode = 0; + myFirstAudioVal = 0; + + myMode = Mode::Volume; + myVolume = DEFAULT_LEVEL; + myVolumeScale = scales[DEFAULT_LEVEL]; + myBright = DEFAULT_LEVEL; + + if (!myStream.open(path)) + return false; + + myStream.swapField(true); + + return true; +} + +void +MovieCart::stopTitleScreen() +{ + writeROM(addr_title_loop + 0, 0x18); // clear carry, one bit difference from 0x38 sec +} + + +void +MovieCart::writeColor(uint16_t address) +{ + uint8_t v = myStream.readColor(); + v = (v & 0xf0) | shiftBright[(v & 0x0f) + myBright]; + + if (myForceColor) + v = myForceColor; + if (myInputs.bw) + v &= 0x0f; + + writeROM(address, v); +} + +void +MovieCart::writeAudioData(uint16_t address, uint8_t val) +{ + uint8_t v; + v = myVolumeScale[val]; + writeROM(address, v); +} + +void +MovieCart::writeAudio(uint16_t address) +{ + uint8_t v = myStream.readAudio(); + writeAudioData(address, v); +} + +void +MovieCart::writeGraph(uint16_t address) +{ + uint8_t v = myStream.readGraph(); + writeROM(address, v); +} + +void +MovieCart::updateTransport() +{ + myStream.overrideGraph(nullptr); + + + // have to cut rate in half, to remove glitches...todo.. + { + if (myBufferIndex == true) + { + uint8_t temp = ~(myA10_Count & 0x1e) & 0x1e; + + if (temp == myDirectionValue) + myInputs.updateDirection(temp); + + myDirectionValue = temp; + } + else + { + uint8_t temp = ~(myA10_Count & 0x17) & 0x17; + + if (temp == myButtonsValue) + myInputs.updateTransport(temp); + + myButtonsValue = temp; + } + + myA10_Count = 0; + } + + if (myInputs.reset) + { + myFrameNumber = 1; + myPlaying = true; + myDrawTimeCode = OSD_FRAMES; + + goto update_stream; + } + + uint8_t lastMainMode = myMode; + + if (myInputs.up && !myLastInputs.up) + { + if (myMode == 0) + myMode = Mode::Last; + else + myMode--; + } + else if (myInputs.down && !myLastInputs.down) + { + if (myMode == Mode::Last) + myMode = 0; + else + myMode++; + } + + if (myInputs.left || myInputs.right) + { + myJoyRepeat++; + } + else + { + myJoyRepeat = 0; + mySpeed = 1; + } + + + if (myJoyRepeat & 16) + { + myJoyRepeat = 0; + + if (myInputs.left || myInputs.right) + { + if (myMode == Mode::Time) + { + myDrawTimeCode = OSD_FRAMES; + mySpeed += 4; + if (mySpeed < 0) + mySpeed -= 4; + } + else if (myMode == Mode::Volume) + { + myDrawLevelBars = OSD_FRAMES; + if (myInputs.left) + { + if (myVolume) + myVolume--; + } + else + { + myVolume++; + if (myVolume >= MAX_LEVEL) + myVolume--; + } + } + else if (myMode == Mode::Bright) + { + myDrawLevelBars = OSD_FRAMES; + if (myInputs.left) + { + if (myBright) + myBright--; + } + else + { + myBright++; + if (myBright >= MAX_LEVEL) + myBright--; + } + } + } + } + + + if (myInputs.select && !myLastInputs.select) + { + myDrawTimeCode = OSD_FRAMES; + myFrameNumber -= 60 * BACK_SECONDS + 1; + goto update_stream; + } + + if (myInputs.fire && !myLastInputs.fire) + myPlaying = !myPlaying; + + switch (myMode) + { + case Mode::Time: + if (lastMainMode != myMode) + myDrawTimeCode = OSD_FRAMES; + break; + + case Mode::Bright: + case Mode::Volume: + default: + if (lastMainMode != myMode) + myDrawLevelBars = OSD_FRAMES; + break; + } + + // just draw one + if (myDrawLevelBars > myDrawTimeCode) + myDrawTimeCode = 0; + else + myDrawLevelBars = 0; + + if (myPlaying) + myVolumeScale = scales[myVolume]; + else + myVolumeScale = scales[0]; + + // update frame + + int8_t step = 1; + + if (!myPlaying) // step while paused + { + if (myMode == Mode::Time) + { + if (myInputs.right && !myLastInputs.right) + step = 3; + else if (myInputs.left && !myLastInputs.left) + step = -3; + else + step = (myFrameNumber & 1) ? -1 : 1; + } + else + { + step = (myFrameNumber & 1) ? -1 : 1; + } + } + else + { + if (myMode == Mode::Time) + { + if (myInputs.right) + step = mySpeed; + else if (myInputs.left) + step = -mySpeed; + } + else + { + step = 1; + } + } + + myFrameNumber += step; + if (myFrameNumber < 1) + { + myFrameNumber = 1; + mySpeed = 1; + } + +update_stream: + + myLastInputs = myInputs; + +} + +void +MovieCart::fill_addr_right_line() +{ + writeGraph(addr_right_line + 9); // #GDATA0 + writeGraph(addr_right_line + 13); // #GDATA1 + writeGraph(addr_right_line + 17); // #GDATA2 + writeGraph(addr_right_line + 21); // #GDATA3 + writeGraph(addr_right_line + 23); // #GDATA4 + + writeColor(addr_right_line + 25); // #GCOL0 + writeColor(addr_right_line + 29); // #GCOL1 + writeColor(addr_right_line + 35); // #GCOL2 + writeColor(addr_right_line + 43); // #GCOL3 + writeColor(addr_right_line + 47); // #GCOL4 +} + +void +MovieCart::fill_addr_left_line(bool again) +{ + writeAudio(addr_left_line + 5); // #AUD_DATA + + writeGraph(addr_left_line + 15); // #GDATA5 + writeGraph(addr_left_line + 19); // #GDATA6 + writeGraph(addr_left_line + 23); // #GDATA7 + writeGraph(addr_left_line + 27); // #GDATA8 + writeGraph(addr_left_line + 29); // #GDATA9 + + writeColor(addr_left_line + 31); // #GCOL5 + writeColor(addr_left_line + 35); // #GCOL6 + writeColor(addr_left_line + 41); // #GCOL7 + writeColor(addr_left_line + 49); // #GCOL8 + writeColor(addr_left_line + 53); // #GCOL9 + + writeAudio(addr_left_line + 57); // #AUD_DATA + + // addr_pick_line_end = 0x0ee; + // jmp right_line + // jmp end_lines + if (again) + { + writeROM(addr_pick_continue + 1, LO_JUMP_BYTE(addr_right_line)); + writeROM(addr_pick_continue + 2, HI_JUMP_BYTE(addr_right_line)); + } + else + { + writeROM(addr_pick_continue + 1, LO_JUMP_BYTE(addr_end_lines)); + writeROM(addr_pick_continue + 2, HI_JUMP_BYTE(addr_end_lines)); + } +} + + +void +MovieCart::fill_addr_end_lines() +{ + writeAudio(addr_end_lines_audio + 1); + myFirstAudioVal = myStream.peekAudio(); + + // normally overscan=28, vblank=37 + // todo: clicky noise.. + if (myOdd) + { + writeROM(addr_set_overscan_size + 1, 28); + writeROM(addr_set_vblank_size + 1, 36); + } + else + { + writeROM(addr_set_overscan_size + 1, 29); + writeROM(addr_set_vblank_size + 1, 37); + } + + if (myBufferIndex == false) + { + writeROM(addr_pick_transport + 1, LO_JUMP_BYTE(addr_transport_direction)); + writeROM(addr_pick_transport + 2, HI_JUMP_BYTE(addr_transport_direction)); + } + else + { + writeROM(addr_pick_transport + 1, LO_JUMP_BYTE(addr_transport_buttons)); + writeROM(addr_pick_transport + 2, HI_JUMP_BYTE(addr_transport_buttons)); + } + +} + +void +MovieCart::fill_addr_blank_lines() +{ + uint8_t i; + uint8_t v; + + // version number + myStream.readVersion(); + myStream.readVersion(); + myStream.readVersion(); + myStream.readVersion(); + + // frame number + myStream.readFrame(); + myStream.readFrame(); + v = myStream.readFrame(); + + // make sure we're in sync with frame data + myOdd = (v & 1); + + // 28 overscan + // 3 vsync + // 37 vblank + + if (myOdd) + { + writeAudioData(addr_audio_bank + 0, myFirstAudioVal); + for (i = 1; i < (BLANK_LINE_SIZE + 1); i++) + writeAudio(addr_audio_bank + i); + } + else + { + for (i = 0; i < (BLANK_LINE_SIZE -1); i++) + writeAudio(addr_audio_bank + i); + } + + writeAudio(addr_last_audio + 1); +} + +void +MovieCart::runStateMachine() +{ + switch(myState) + { + case 1: + if (myA7) + { + if (myLines == (TIMECODE_HEIGHT-1)) + { + if (myDrawTimeCode) + { + myDrawTimeCode--; + myForceColor = COLOR_BLUE; + myStream.startTimeCode(); + } + } + + // label = 12, bars = 7 + if (myLines == 21) + { + if (myDrawLevelBars) + { + myDrawLevelBars--; + myForceColor = COLOR_BLUE; + + switch (myMode) + { + case Mode::Time: + myStream.overrideGraph(nullptr); + break; + + case Mode::Bright: + if (myOdd) + myStream.overrideGraph(brightLabelOdd); + else + myStream.overrideGraph(brightLabelEven); + break; + + case Mode::Volume: + default: + if (myOdd) + myStream.overrideGraph(volumeLabelOdd); + else + myStream.overrideGraph(volumeLabelEven); + break; + } + } + } + + if (myLines == 7) + { + if (myDrawLevelBars) + { + uint8_t levelValue; + + switch (myMode) + { + case Mode::Time: + levelValue = 0; + break; + + case Mode::Bright: + levelValue = myBright; + break; + + case Mode::Volume: + default: + levelValue = myVolume; + break; + } + + if (myOdd) + myStream.overrideGraph(&levelBarsOddData[levelValue * 40]); + else + myStream.overrideGraph(&levelBarsEvenData[levelValue * 40]); + } + } + + fill_addr_right_line(); + + myLines -= 1; + myState = 2; + } + break; + + + case 2: + if (!myA7) + { + if (myLines >= 1) + { + fill_addr_left_line(1); + + myLines -= 1; + myState = 1; + } + else + { + fill_addr_left_line(0); + fill_addr_end_lines(); + + myStream.swapField(myBufferIndex); + myBufferIndex = !myBufferIndex; + updateTransport(); + + fill_addr_blank_lines(); + + myState = 3; + } + } + break; + + case 3: + if (myA7) + { + // hit end? rewind just before end + while (myFrameNumber >= 2 && !myStream.readField(myFrameNumber, myBufferIndex)) + { + myFrameNumber -= 2; + myJoyRepeat = 0; + } + + myForceColor = 0; + myLines = 191; + myState = 1; + } + break; + + default: + break; + } +} + +bool +MovieCart::process(uint16_t address) +{ + + bool a12 = (address & (1 << 12)) ? 1:0; + bool a11 = (address & (1 << 11)) ? 1:0; + + // count a10 pulses + bool a10i = (address & (1 << 10)); + if (a10i && !myA10) + myA10_Count++; + myA10 = a10i; + + // latch a7 state + if (a11) // a12 + myA7 = (address & (1 << 7)); // each 128 + + switch(myTitleState) + { + case TitleState::Display: + myTitleCycles++; + if (myTitleCycles == TITLE_CYCLES) + { + stopTitleScreen(); + myTitleState = TitleState::Exiting; + myTitleCycles = 0; + } + break; + + case TitleState::Exiting: + if (myA7) + myTitleState = TitleState::Stream; + break; + + case TitleState::Stream: + runStateMachine(); + break; + } + + return a12; +} + diff --git a/src/emucore/MovieCart/MovieCart.hxx b/src/emucore/MovieCart/MovieCart.hxx new file mode 100755 index 000000000..b58c1c0db --- /dev/null +++ b/src/emucore/MovieCart/MovieCart.hxx @@ -0,0 +1,147 @@ +//============================================================================ +// +// SSSS tt lll lll +// SS SS tt ll ll +// SS tttttt eeee ll ll aaaa +// SSSS tt ee ee ll ll aa +// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" +// SS SS tt ee ll ll aa aa +// SSSS ttt eeeee llll llll aaaaa +// +// Copyright (c) 1995-2021 by Bradford W. Mott, Stephen Anthony +// and the Stella Team +// +// See the file "License.txt" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +//============================================================================ +// Key kernel positions, automatically generated + +/** + Implementation of MovieCart. + 1K of memory is presented on the bus, but is repeated to fill the 4K image space. + Contents are dynamically altered with streaming image and audio content as specific + 128-byte regions are entered. + Original implementation: github.com/lodefmode/moviecart + + @author Rob Bairos +*/ + +#pragma once + +#include +#include "StreamReader.hxx" +#include "MovieInputs.hxx" + +class MovieCart +{ + +public: + + MovieCart() + { + } + + ~MovieCart() + { + } + + bool init(const std::string& path); + bool process(uint16_t address); + + uint8_t + readROM(uint16_t address) + { + return myROM[address & 1023]; + } + + void + writeROM(uint16_t address, uint8_t data) + { + myROM[address & 1023] = data; + } + +private: + + enum Mode + { + Volume, + Bright, + Time, + Last = Time + }; + + enum TitleState + { + Display, + Exiting, + Stream + }; + + + void stopTitleScreen(); + + void writeColor(uint16_t address); + void writeAudioData(uint16_t address, uint8_t val); + void writeAudio(uint16_t address); + void writeGraph(uint16_t address); + + void runStateMachine(); + + void fill_addr_right_line(); + void fill_addr_left_line(bool again); + void fill_addr_end_lines(); + void fill_addr_blank_lines(); + + void updateTransport(); + + + StreamReader myStream; + + // data + + uint8_t myROM[1024]; + + + // title screen state + int myTitleCycles; + uint8_t myTitleState; + + + // address info + bool myA7; + bool myA10; + uint8_t myA10_Count; + + // state machine info + + uint8_t myState; + bool myPlaying; + bool myOdd; + bool myBufferIndex; + + + uint8_t myLines; + int32_t myFrameNumber; // signed + + uint8_t myMode; + uint8_t myBright; + uint8_t myForceColor; + + // expressed in frames + uint8_t myDrawLevelBars; + uint8_t myDrawTimeCode; + + MovieInputs myInputs; + MovieInputs myLastInputs; + int8_t mySpeed; // signed + uint8_t myJoyRepeat; + uint8_t myDirectionValue; + uint8_t myButtonsValue; + + uint8_t myVolume; + const uint8_t* myVolumeScale; + uint8_t myFirstAudioVal; + +}; + + diff --git a/src/emucore/MovieCart/MovieInputs.hxx b/src/emucore/MovieCart/MovieInputs.hxx new file mode 100755 index 000000000..20c31f0e5 --- /dev/null +++ b/src/emucore/MovieCart/MovieInputs.hxx @@ -0,0 +1,91 @@ +//============================================================================ +// +// SSSS tt lll lll +// SS SS tt ll ll +// SS tttttt eeee ll ll aaaa +// SSSS tt ee ee ll ll aa +// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" +// SS SS tt ee ll ll aa aa +// SSSS ttt eeeee llll llll aaaaa +// +// Copyright (c) 1995-2021 by Bradford W. Mott, Stephen Anthony +// and the Stella Team +// +// See the file "License.txt" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +//============================================================================ +// Key kernel positions, automatically generated + +/** + State of current switches and joystick positions to control MovieCart + @author Rob Bairos +*/ + +#pragma once + +class MovieInputs +{ +public: + + MovieInputs() + { + init(); + } + + void + init() + { + bw = false; + fire = false; + select = false; + reset = false; + + right = false; + left = false; + up = false; + down = false; + } + + bool bw; + bool fire; + bool select; + bool reset; + + bool right; + bool left; + bool up; + bool down; + + void + updateDirection(uint8_t val) + { + right = val & TRANSPORT_RIGHT; + left = val & TRANSPORT_LEFT; + up = val & TRANSPORT_UP; + down = val & TRANSPORT_DOWN; + } + + void updateTransport(uint8_t val) + { + bw = val & TRANSPORT_BW; + fire = val & TRANSPORT_BUTTON; + select = val & TRANSPORT_SELECT; + reset = val & TRANSPORT_RESET; + } + +private: + + static int constexpr TRANSPORT_RIGHT = 0x10; + static int constexpr TRANSPORT_LEFT = 0x08; + static int constexpr TRANSPORT_DOWN = 0x04; + static int constexpr TRANSPORT_UP = 0x02; + static int constexpr TRANSPORT_UNUSED1 = 0x01; // Right-2 + + static int constexpr TRANSPORT_BW = 0x10; + static int constexpr TRANSPORT_UNUSED2 = 0x08; + static int constexpr TRANSPORT_SELECT = 0x04; + static int constexpr TRANSPORT_RESET = 0x02; + static int constexpr TRANSPORT_BUTTON = 0x01; + +}; + diff --git a/src/emucore/MovieCart/StreamReader.cxx b/src/emucore/MovieCart/StreamReader.cxx new file mode 100755 index 000000000..9029b5858 --- /dev/null +++ b/src/emucore/MovieCart/StreamReader.cxx @@ -0,0 +1,96 @@ +//============================================================================ +// +// SSSS tt lll lll +// SS SS tt ll ll +// SS tttttt eeee ll ll aaaa +// SSSS tt ee ee ll ll aa +// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" +// SS SS tt ee ll ll aa aa +// SSSS ttt eeeee llll llll aaaaa +// +// Copyright (c) 1995-2021 by Bradford W. Mott, Stephen Anthony +// and the Stella Team +// +// See the file "License.txt" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +//============================================================================ +// Key kernel positions, automatically generated + +/** + Simulate retrieval of 512 byte chunks from a serial source + @author Rob Bairos +*/ + +#include "StreamReader.hxx" + +bool +StreamReader::open(const std::string& path) +{ + close(); + + myFile = new std::ifstream(path, std::ios::binary); + + if (!myFile || !*myFile) + close(); + + myFile->seekg(0, std::ios::end); + myFileSize = static_cast(myFile->tellg()); + myFile->seekg(0, std::ios::beg); + + return myFile ? true:false; +} + +void +StreamReader::close() +{ + delete myFile; + myFile = nullptr; +} + +void +StreamReader::swapField(bool index) +{ + if (index == true) + { + myVersion = myBuffer1 + VERSION_DATA_OFFSET; + myFrame = myBuffer1 + FRAME_DATA_OFFSET; + myAudio = myBuffer1 + AUDIO_DATA_OFFSET; + myGraph = myBuffer1 + GRAPH_DATA_OFFSET; + myTimecode= myBuffer1 + TIMECODE_DATA_OFFSET; + myColor = myBuffer1 + COLOR_DATA_OFFSET; + } + else + { + myVersion = myBuffer2 + VERSION_DATA_OFFSET; + myFrame = myBuffer2 + FRAME_DATA_OFFSET; + myAudio = myBuffer2 + AUDIO_DATA_OFFSET; + myGraph = myBuffer2 + GRAPH_DATA_OFFSET; + myTimecode = myBuffer2 + TIMECODE_DATA_OFFSET; + myColor = myBuffer2 + COLOR_DATA_OFFSET; + } +} + +bool +StreamReader::readField(uint32_t fnum, bool index) +{ + bool read = false; + + if (myFile) + { + size_t offset = ((fnum + 0) * MVC_FIELD_PAD_SIZE); + + if (offset + MVC_FIELD_PAD_SIZE < myFileSize) + { + myFile->seekg(offset); + if (index == true) + myFile->read((char*)myBuffer1, MVC_FIELD_SIZE); + else + myFile->read((char*)myBuffer2, MVC_FIELD_SIZE); + + read = true; + } + } + + return read; +} + diff --git a/src/emucore/MovieCart/StreamReader.hxx b/src/emucore/MovieCart/StreamReader.hxx new file mode 100755 index 000000000..61a0b33e1 --- /dev/null +++ b/src/emucore/MovieCart/StreamReader.hxx @@ -0,0 +1,135 @@ +//============================================================================ +// +// SSSS tt lll lll +// SS SS tt ll ll +// SS tttttt eeee ll ll aaaa +// SSSS tt ee ee ll ll aa +// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" +// SS SS tt ee ll ll aa aa +// SSSS ttt eeeee llll llll aaaaa +// +// Copyright (c) 1995-2021 by Bradford W. Mott, Stephen Anthony +// and the Stella Team +// +// See the file "License.txt" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +//============================================================================ +// Key kernel positions, automatically generated + +/** + Simulate retrieval 512 byte chunks from a serial source + @author Rob Bairos +*/ + +#pragma once + +#include +#include +#include + +#define MVC_FIELD_SIZE 2560 // round field to nearest 512 byte boundary +#define MVC_FIELD_PAD_SIZE 4096 // round to nearest 4K + +class StreamReader +{ +public: + + StreamReader() + { + } + + ~StreamReader() + { + close(); + } + + bool open(const std::string& path); + void close(); + void swapField(bool index); + bool readField(uint32_t fnum, bool index); + + uint8_t + readVersion() + { + return *myVersion++; + } + + uint8_t + readFrame() + { + return *myFrame++; + } + + uint8_t + readColor() + { + return *myColor++; + } + + uint8_t + readGraph() + { + uint8_t v; + + if (myGraphOverride) + v = *myGraphOverride++; + else + v = *myGraph++; + + return v; + } + + void + overrideGraph(const uint8_t* p) + { + myGraphOverride = p; + } + + uint8_t + readAudio() + { + return *myAudio++; + } + + uint8_t + peekAudio() + { + return *myAudio; + } + + void + startTimeCode() + { + myGraph = myTimecode; + } + + +private: + + static int constexpr VERSION_DATA_OFFSET = 0; + static int constexpr FRAME_DATA_OFFSET = 4; + static int constexpr AUDIO_DATA_OFFSET = 7; + static int constexpr GRAPH_DATA_OFFSET = 269; + static int constexpr TIMECODE_DATA_OFFSET = 1229; + static int constexpr COLOR_DATA_OFFSET = 1289; + static int constexpr END_DATA_OFFSET = 2249; + + + const uint8_t* myAudio{nullptr}; + + const uint8_t* myGraph{nullptr}; + const uint8_t* myGraphOverride{nullptr}; + + const uint8_t* myTimecode{nullptr}; + const uint8_t* myColor{nullptr}; + const uint8_t* myVersion{nullptr}; + const uint8_t* myFrame{nullptr}; + + uint8_t myBuffer1[MVC_FIELD_SIZE]; + uint8_t myBuffer2[MVC_FIELD_SIZE]; + + std::ifstream* myFile{nullptr}; + size_t myFileSize{0}; + +}; + diff --git a/src/windows/Stella.vcxproj b/src/windows/Stella.vcxproj index edf8751ee..1d890a299 100644 --- a/src/windows/Stella.vcxproj +++ b/src/windows/Stella.vcxproj @@ -753,6 +753,7 @@ + @@ -763,6 +764,8 @@ + + @@ -1817,6 +1820,7 @@ + @@ -1833,6 +1837,10 @@ + + + + diff --git a/src/windows/Stella.vcxproj.filters b/src/windows/Stella.vcxproj.filters index f65dd22bb..67c3394df 100644 --- a/src/windows/Stella.vcxproj.filters +++ b/src/windows/Stella.vcxproj.filters @@ -1110,6 +1110,15 @@ Source Files\repository + + Source Files\emucore + + + Source Files\emucore + + + Source Files\emucore + @@ -2282,6 +2291,21 @@ Header Files\emucore + + Header Files\emucore + + + Header Files\emucore + + + Header Files\emucore + + + Header Files\emucore + + + Header Files\emucore + From 0e39371e769ffffb308c4934bcf31165493ae696 Mon Sep 17 00:00:00 2001 From: Rob Bairos Date: Mon, 5 Apr 2021 09:27:51 -0400 Subject: [PATCH 02/17] (MovieCart) Limit reading of image data to single frame when its likely an MVC file. This avoids reading of GB of data. --- src/emucore/CartDetector.cxx | 28 ++++++++++++++++++++++++++-- src/emucore/CartDetector.hxx | 7 +++++++ src/emucore/FSNode.cxx | 7 +++++++ 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/src/emucore/CartDetector.cxx b/src/emucore/CartDetector.cxx index 6d5713f2e..6b443e297 100644 --- a/src/emucore/CartDetector.cxx +++ b/src/emucore/CartDetector.cxx @@ -19,6 +19,7 @@ #include "Logger.hxx" #include "CartDetector.hxx" +#include "MovieCart/StreamReader.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Bankswitch::Type CartDetector::autodetectType(const ByteBuffer& image, size_t size) @@ -694,11 +695,34 @@ bool CartDetector::isProbablyMDM(const ByteBuffer& image, size_t size) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool CartDetector::isProbablyMVC(const ByteBuffer& image, size_t size) { - // MVC version 0, frame 0 + // MVC version 0 uInt8 sig[] = { 'M', 'V', 'C', 0 }; - return searchForBytes(image, std::min(size, 5), sig, 4); + int sigSize = sizeof(sig); + return searchForBytes(image, std::min(size, sigSize+1), sig, sigSize); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +size_t CartDetector::isProbablyMVC(std::istream &in, size_t maxSize) +{ + const size_t frameSize = 2 * MVC_FIELD_PAD_SIZE; + bool found = false; + + // Returns size of field if stream is probably an MVC movie cartridge + + if (maxSize >= frameSize) + { + auto pos = in.tellg(); + + ByteBuffer image = make_unique(frameSize); + in.read(reinterpret_cast(image.get()), frameSize); + + in.seekg(pos); + + found = isProbablyMVC(image, frameSize); + } + + return found ? frameSize : 0; +} // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool CartDetector::isProbablySB(const ByteBuffer& image, size_t size) diff --git a/src/emucore/CartDetector.hxx b/src/emucore/CartDetector.hxx index 0061b1054..d845dad78 100644 --- a/src/emucore/CartDetector.hxx +++ b/src/emucore/CartDetector.hxx @@ -40,6 +40,13 @@ class CartDetector */ static Bankswitch::Type autodetectType(const ByteBuffer& image, size_t size); + + /** + MVC cartridges are of arbitary large length + Returns size of frame if stream is probably an MVC movie cartridge + */ + static size_t isProbablyMVC(std::istream &in, size_t size); + private: /** Search the image for the specified byte signature diff --git a/src/emucore/FSNode.cxx b/src/emucore/FSNode.cxx index b0aa64394..28a6100f5 100644 --- a/src/emucore/FSNode.cxx +++ b/src/emucore/FSNode.cxx @@ -17,6 +17,7 @@ #include "FSNodeFactory.hxx" #include "FSNode.hxx" +#include "CartDetector.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - FilesystemNode::FilesystemNode(const AbstractFSNodePtr& realNode) @@ -355,6 +356,12 @@ size_t FilesystemNode::read(ByteBuffer& buffer) const if (sizeRead == 0) throw runtime_error("Zero-byte file"); + // In the case of MVC (MovieCart) files, contents are streaming data + // of arbitrary length, so just read first frame. + size_t subSize = CartDetector::isProbablyMVC(in, sizeRead); + if (subSize > 0) + sizeRead = subSize; + buffer = make_unique(sizeRead); in.read(reinterpret_cast(buffer.get()), sizeRead); } From 65180d524fdd1f9b3cbf674e6304816702bd0a99 Mon Sep 17 00:00:00 2001 From: Lo Def Date: Mon, 5 Apr 2021 23:39:26 -0400 Subject: [PATCH 03/17] (MovieCart) combined subfolder of classes into CartMVC --- src/emucore/CartDetector.cxx | 2 +- src/emucore/CartMVC.cxx | 1396 +++++++++++++++++++++++- src/emucore/CartMVC.hxx | 10 +- src/emucore/MovieCart/KernelData.hxx | 421 ------- src/emucore/MovieCart/MovieCart.cxx | 626 ----------- src/emucore/MovieCart/MovieCart.hxx | 147 --- src/emucore/MovieCart/MovieInputs.hxx | 91 -- src/emucore/MovieCart/StreamReader.cxx | 96 -- src/emucore/MovieCart/StreamReader.hxx | 135 --- src/windows/Stella.vcxproj | 6 - src/windows/Stella.vcxproj.filters | 18 - 11 files changed, 1399 insertions(+), 1549 deletions(-) delete mode 100755 src/emucore/MovieCart/KernelData.hxx delete mode 100755 src/emucore/MovieCart/MovieCart.cxx delete mode 100755 src/emucore/MovieCart/MovieCart.hxx delete mode 100755 src/emucore/MovieCart/MovieInputs.hxx delete mode 100755 src/emucore/MovieCart/StreamReader.cxx delete mode 100755 src/emucore/MovieCart/StreamReader.hxx mode change 100644 => 100755 src/windows/Stella.vcxproj diff --git a/src/emucore/CartDetector.cxx b/src/emucore/CartDetector.cxx index 6b443e297..a0765622d 100644 --- a/src/emucore/CartDetector.cxx +++ b/src/emucore/CartDetector.cxx @@ -19,7 +19,7 @@ #include "Logger.hxx" #include "CartDetector.hxx" -#include "MovieCart/StreamReader.hxx" +#include "CartMVC.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Bankswitch::Type CartDetector::autodetectType(const ByteBuffer& image, size_t size) diff --git a/src/emucore/CartMVC.cxx b/src/emucore/CartMVC.cxx index ab05cd0b1..f30c4393e 100755 --- a/src/emucore/CartMVC.cxx +++ b/src/emucore/CartMVC.cxx @@ -18,6 +18,1391 @@ #include "System.hxx" #include "CartMVC.hxx" + +/** + Implementation of MovieCart. + 1K of memory is presented on the bus, but is repeated to fill the 4K image space. + Contents are dynamically altered with streaming image and audio content as specific + 128-byte regions are entered. + Original implementation: github.com/lodefmode/moviecart + + @author Rob Bairos +*/ + +#include +#include +#include +#include + +#define LO_JUMP_BYTE(X) ((X) & 0xff) +#define HI_JUMP_BYTE(X) ((((X) & 0xff00) >> 8) | 0x10) + +#define COLOR_BLUE 0x9A +#define COLOR_WHITE 0x0E + +#define OSD_FRAMES 180 +#define BACK_SECONDS 10 + +#define TITLE_CYCLES 1000000 + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +/** + Simulate retrieval 512 byte chunks from a serial source +*/ + +class StreamReader +{ +public: + + StreamReader() + { + } + + ~StreamReader() + { + close(); + } + + bool open(const std::string& path); + void close(); + void swapField(bool index); + bool readField(uint32_t fnum, bool index); + + uint8_t + readVersion() + { + return *myVersion++; + } + + uint8_t + readFrame() + { + return *myFrame++; + } + + uint8_t + readColor() + { + return *myColor++; + } + + uint8_t + readGraph() + { + uint8_t v; + + if (myGraphOverride) + v = *myGraphOverride++; + else + v = *myGraph++; + + return v; + } + + void + overrideGraph(const uint8_t* p) + { + myGraphOverride = p; + } + + uint8_t + readAudio() + { + return *myAudio++; + } + + uint8_t + peekAudio() + { + return *myAudio; + } + + void + startTimeCode() + { + myGraph = myTimecode; + } + + +private: + + static int constexpr VERSION_DATA_OFFSET = 0; + static int constexpr FRAME_DATA_OFFSET = 4; + static int constexpr AUDIO_DATA_OFFSET = 7; + static int constexpr GRAPH_DATA_OFFSET = 269; + static int constexpr TIMECODE_DATA_OFFSET = 1229; + static int constexpr COLOR_DATA_OFFSET = 1289; + static int constexpr END_DATA_OFFSET = 2249; + + + const uint8_t* myAudio{nullptr}; + + const uint8_t* myGraph{nullptr}; + const uint8_t* myGraphOverride{nullptr}; + + const uint8_t* myTimecode{nullptr}; + const uint8_t* myColor{nullptr}; + const uint8_t* myVersion{nullptr}; + const uint8_t* myFrame{nullptr}; + + uint8_t myBuffer1[MVC_FIELD_SIZE]; + uint8_t myBuffer2[MVC_FIELD_SIZE]; + + std::ifstream* myFile{nullptr}; + size_t myFileSize{0}; + +}; + +bool +StreamReader::open(const std::string& path) +{ + close(); + + myFile = new std::ifstream(path, std::ios::binary); + + if (!myFile || !*myFile) + close(); + + myFile->seekg(0, std::ios::end); + myFileSize = static_cast(myFile->tellg()); + myFile->seekg(0, std::ios::beg); + + return myFile ? true:false; +} + +void +StreamReader::close() +{ + delete myFile; + myFile = nullptr; +} + +void +StreamReader::swapField(bool index) +{ + if (index == true) + { + myVersion = myBuffer1 + VERSION_DATA_OFFSET; + myFrame = myBuffer1 + FRAME_DATA_OFFSET; + myAudio = myBuffer1 + AUDIO_DATA_OFFSET; + myGraph = myBuffer1 + GRAPH_DATA_OFFSET; + myTimecode= myBuffer1 + TIMECODE_DATA_OFFSET; + myColor = myBuffer1 + COLOR_DATA_OFFSET; + } + else + { + myVersion = myBuffer2 + VERSION_DATA_OFFSET; + myFrame = myBuffer2 + FRAME_DATA_OFFSET; + myAudio = myBuffer2 + AUDIO_DATA_OFFSET; + myGraph = myBuffer2 + GRAPH_DATA_OFFSET; + myTimecode = myBuffer2 + TIMECODE_DATA_OFFSET; + myColor = myBuffer2 + COLOR_DATA_OFFSET; + } +} + +bool +StreamReader::readField(uint32_t fnum, bool index) +{ + bool read = false; + + if (myFile) + { + size_t offset = ((fnum + 0) * MVC_FIELD_PAD_SIZE); + + if (offset + MVC_FIELD_PAD_SIZE < myFileSize) + { + myFile->seekg(offset); + if (index == true) + myFile->read((char*)myBuffer1, MVC_FIELD_SIZE); + else + myFile->read((char*)myBuffer2, MVC_FIELD_SIZE); + + read = true; + } + } + + return read; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +/** + State of current switches and joystick positions to control MovieCart +*/ + +class MovieInputs +{ +public: + + MovieInputs() + { + init(); + } + + void + init() + { + bw = false; + fire = false; + select = false; + reset = false; + + right = false; + left = false; + up = false; + down = false; + } + + bool bw; + bool fire; + bool select; + bool reset; + + bool right; + bool left; + bool up; + bool down; + + void + updateDirection(uint8_t val) + { + right = val & TRANSPORT_RIGHT; + left = val & TRANSPORT_LEFT; + up = val & TRANSPORT_UP; + down = val & TRANSPORT_DOWN; + } + + void updateTransport(uint8_t val) + { + bw = val & TRANSPORT_BW; + fire = val & TRANSPORT_BUTTON; + select = val & TRANSPORT_SELECT; + reset = val & TRANSPORT_RESET; + } + +private: + + static int constexpr TRANSPORT_RIGHT = 0x10; + static int constexpr TRANSPORT_LEFT = 0x08; + static int constexpr TRANSPORT_DOWN = 0x04; + static int constexpr TRANSPORT_UP = 0x02; + static int constexpr TRANSPORT_UNUSED1 = 0x01; // Right-2 + + static int constexpr TRANSPORT_BW = 0x10; + static int constexpr TRANSPORT_UNUSED2 = 0x08; + static int constexpr TRANSPORT_SELECT = 0x04; + static int constexpr TRANSPORT_RESET = 0x02; + static int constexpr TRANSPORT_BUTTON = 0x01; + +}; + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + +/** + Various kernel, OSD and scale definitions + @author Rob Bairos +*/ + + +#define TIMECODE_HEIGHT 12 +#define MAX_LEVEL 11 +#define DEFAULT_LEVEL 6 +#define BLANK_LINE_SIZE (28+3+37) // 68 + +#define addr_kernel_48 0x800 +#define addr_transport_buttons 0x880 +#define addr_transport_direction 0x897 +#define addr_right_line 0x94c +#define addr_left_line 0x980 +#define addr_pick_continue 0x9c2 +#define addr_main_start 0xa00 +#define addr_aud_bank_setup 0xa0c +#define addr_tg0 0xa24 +#define addr_title_again 0xa3b +#define addr_end_lines 0xa80 +#define addr_end_lines_audio 0xaa1 +#define addr_set_overscan_size 0xaad +#define addr_set_vblank_size 0xac3 +#define addr_pick_transport 0xacc +#define addr_last_audio 0xacf +#define addr_wait_lines 0xad4 +#define addr_transport_done1 0xae7 +#define addr_draw_title 0xb00 +#define addr_title_loop 0xb50 +#define addr_black_bar 0xb52 +#define addr_animate_bar1 0xb58 +#define addr_animate_bar_again1 0xb5a +#define addr_animate_dex1 0xb65 +#define addr_audio_bank 0xb80 +#define addr_reset_loop 0xbfa + +// scale adjustments, automatically generated +const uint8_t scale0[16] = { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}; /* 0.0000 */ +const uint8_t scale1[16] = { 6, 6, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 9, 9}; /* 0.1667 */ +const uint8_t scale2[16] = { 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10}; /* 0.3333 */ +const uint8_t scale3[16] = { 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11}; /* 0.5000 */ +const uint8_t scale4[16] = { 3, 3, 4, 5, 5, 6, 7, 7, 8, 9, 9, 10, 11, 11, 12, 13}; /* 0.6667 */ +const uint8_t scale5[16] = { 1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 10, 10, 11, 12, 13, 14}; /* 0.8333 */ +const uint8_t scale6[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; /* 1.0000 */ +const uint8_t scale7[16] = { 0, 0, 0, 1, 3, 4, 5, 7, 8, 10, 11, 12, 14, 15, 15, 15}; /* 1.3611 */ +const uint8_t scale8[16] = { 0, 0, 0, 0, 1, 3, 5, 7, 8, 10, 12, 14, 15, 15, 15, 15}; /* 1.7778 */ +const uint8_t scale9[16] = { 0, 0, 0, 0, 0, 2, 4, 6, 9, 11, 13, 15, 15, 15, 15, 15}; /* 2.2500 */ +const uint8_t scale10[16] = { 0, 0, 0, 0, 0, 1, 3, 6, 9, 12, 14, 15, 15, 15, 15, 15}; /* 2.7778 */ +const uint8_t *scales[11] = {scale0, scale1, scale2, scale3, scale4, scale5, scale6, scale7, scale8, scale9, scale10}; + +// lower bit is ignored anyways +const uint8_t shiftBright[16 + MAX_LEVEL - 1] = { 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 15, 15, 15, 15}; + +// Compiled kernel +const unsigned char kernelROM[] = +{ + 133, 2, 185, 50, 248, 133, 27, 185, 62, 248, 133, 28, 185, 74, 248, 133, + 27, 185, 86, 248, 133, 135, 185, 98, 248, 190, 110, 248, 132, 136, 164, 135, + 132, 28, 133, 27, 134, 28, 134, 27, 164, 136, 102, 137, 176, 210, 136, 16, + 207, 96, 0, 1, 1, 1, 0, 0, 48, 48, 50, 53, 56, 48, 249, 129, + 129, 128, 248, 0, 99, 102, 102, 102, 230, 99, 140, 252, 140, 136, 112, 0, + 192, 97, 99, 102, 102, 198, 198, 198, 248, 198, 248, 0, 193, 32, 48, 24, + 24, 25, 24, 24, 24, 24, 126, 0, 249, 97, 97, 97, 97, 249, 0, 0, + 0, 0, 0, 0, 248, 128, 128, 224, 128, 248, 255, 255, 255, 255, 255, 255, + 165, 12, 10, 173, 130, 2, 42, 41, 23, 133, 129, 133, 128, 133, 128, 133, + 128, 133, 128, 133, 128, 234, 96, 173, 128, 2, 74, 74, 74, 133, 129, 133, + 128, 133, 128, 133, 128, 133, 128, 133, 128, 133, 128, 234, 96, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 133, 25, 133, 128, + 134, 32, 134, 33, 169, 243, 133, 27, 169, 207, 133, 28, 169, 251, 133, 27, + 169, 239, 162, 191, 160, 66, 133, 28, 169, 54, 133, 6, 134, 27, 169, 238, + 133, 7, 132, 6, 132, 28, 169, 182, 133, 6, 169, 114, 133, 7, 133, 42, + 162, 0, 162, 0, 169, 0, 162, 128, 133, 25, 134, 32, 134, 33, 169, 231, + 133, 27, 169, 159, 133, 28, 169, 253, 133, 27, 169, 247, 162, 223, 160, 242, + 133, 28, 169, 248, 133, 6, 134, 27, 169, 172, 133, 7, 132, 6, 132, 28, + 169, 216, 133, 6, 169, 98, 133, 7, 169, 0, 162, 0, 162, 0, 162, 0, + 133, 42, 76, 76, 249, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 120, 216, 162, 255, 154, 169, 0, 149, 0, 202, 208, 251, 169, 128, 133, 130, + 169, 251, 133, 131, 169, 1, 133, 37, 133, 38, 169, 3, 133, 4, 133, 5, + 133, 2, 162, 4, 133, 128, 202, 208, 251, 133, 128, 133, 16, 133, 17, 169, + 208, 133, 32, 169, 224, 133, 33, 133, 2, 133, 42, 165, 132, 106, 106, 133, + 6, 133, 7, 169, 85, 133, 137, 32, 0, 251, 176, 239, 169, 0, 133, 9, + 141, 129, 2, 141, 131, 2, 169, 6, 133, 4, 169, 2, 133, 5, 169, 0, + 133, 2, 133, 128, 76, 128, 250, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 133, 25, 169, 0, 133, 27, 133, 28, 133, 27, 133, 28, 133, 128, 133, 128, + 133, 128, 169, 0, 133, 16, 234, 133, 17, 169, 208, 133, 32, 169, 192, 133, + 33, 169, 0, 133, 2, 133, 42, 133, 128, 133, 25, 160, 0, 162, 28, 32, + 212, 250, 169, 2, 133, 0, 162, 3, 32, 212, 250, 169, 0, 133, 0, 169, + 2, 133, 1, 162, 37, 32, 212, 250, 162, 0, 134, 1, 32, 128, 248, 169, + 0, 76, 76, 249, 177, 130, 133, 2, 133, 128, 133, 128, 133, 25, 165, 129, + 240, 5, 198, 129, 173, 128, 20, 200, 202, 208, 233, 96, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 162, 30, 32, 82, 251, 169, 2, 133, 0, 162, 3, 32, 82, 251, 169, 0, + 133, 0, 169, 2, 133, 1, 162, 37, 32, 82, 251, 169, 0, 133, 1, 198, + 132, 165, 132, 133, 133, 160, 255, 162, 30, 32, 88, 251, 162, 54, 32, 82, + 251, 160, 11, 32, 0, 248, 169, 0, 133, 27, 133, 28, 133, 27, 133, 28, + 162, 54, 32, 82, 251, 165, 132, 133, 133, 160, 1, 162, 30, 32, 88, 251, + 56, 96, 169, 0, 133, 133, 160, 0, 132, 134, 24, 165, 133, 101, 134, 133, + 133, 133, 2, 133, 9, 202, 208, 242, 96, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 250, 0, 250, 0, 250, +}; + +// OSD labels + +const uint8_t brightLabelEven[] = +{ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 225, 48, 12, 252, + 6, 140, 231, 96, 0, + 0, 113, 48, 12, 96, + 6, 140, 192, 96, 0, + 0, 225, 49, 15, 96, + 6, 152, 195, 96, 0, + 0, 49, 48, 12, 96, + 6, 140, 231, 96, 0, + 0, 225, 48, 12, 96, +}; + +const uint8_t brightLabelOdd[] = +{ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 7, 252, 126, 99, 0, + 0, 113, 48, 12, 96, + 6, 140, 192, 96, 0, + 0, 97, 49, 12, 96, + 7, 248, 223, 224, 0, + 0, 113, 49, 12, 96, + 6, 156, 195, 96, 0, + 0, 113, 48, 12, 96, + 7, 142, 127, 96, 0, + 0, 0, 0, 0, 0 +}; + +const uint8_t volumeLabelEven[] = +{ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 199, 192, 14, 254, + 113, 112, 99, 112, 0, + 0, 140, 192, 14, 192, + 51, 48, 99, 240, 0, + 0, 28, 192, 15, 254, + 31, 48, 99, 240, 0, + 0, 12, 192, 15, 192, + 30, 112, 119, 176, 0, + 0, 7, 252, 12, 254, +}; + +const uint8_t volumeLabelOdd[] = +{ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 97, 224, 99, 112, 0, + 0, 142, 192, 14, 192, + 51, 112, 99, 112, 0, + 0, 28, 192, 15, 192, + 59, 48, 99, 240, 0, + 0, 28, 192, 15, 192, + 30, 112, 99, 176, 0, + 0, 14, 192, 13, 192, + 14, 224, 62, 48, 0, + 0, 0, 0, 0, 0 +}; + +// Level bars +// 8 rows * 5 columns = 40 + +const uint8_t levelBarsEvenData[] = +{ + /**/ + 0, 0, 0, 0, 0, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 2, 40, 161, 133, 20, + 20, 80, 66, 10, 32, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 0, 0, 0, 0, 0, + /**/ + 0, 0, 0, 0, 0, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 3, 40, 161, 133, 20, + 244, 80, 66, 10, 32, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 0, 0, 0, 0, 0, + /**/ + 0, 0, 0, 0, 0, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 3, 232, 161, 133, 20, + 247, 80, 66, 10, 32, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 0, 0, 0, 0, 0, + /**/ + 0, 0, 0, 0, 0, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 3, 239, 161, 133, 20, + 247, 208, 66, 10, 32, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 0, 0, 0, 0, 0, + /**/ + 0, 0, 0, 0, 0, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 3, 239, 161, 133, 20, + 247, 223, 66, 10, 32, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 0, 0, 0, 0, 0, + /**/ + 0, 0, 0, 0, 0, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 3, 239, 191, 133, 20, + 247, 223, 66, 10, 32, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 0, 0, 0, 0, 0, + /**/ + 0, 0, 0, 0, 0, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 3, 239, 191, 133, 20, + 247, 223, 126, 10, 32, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 0, 0, 0, 0, 0, + /**/ + 0, 0, 0, 0, 0, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 20, + 247, 223, 126, 10, 32, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 0, 0, 0, 0, 0, + /**/ + 0, 0, 0, 0, 0, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 20, + 247, 223, 126, 250, 32, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 0, 0, 0, 0, 0, + /**/ + 0, 0, 0, 0, 0, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 244, + 247, 223, 126, 251, 32, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 0, 0, 0, 0, 0, + /**/ + 0, 0, 0, 0, 0, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 0, 0, 0, 0, 0, + +}; + +const uint8_t levelBarsOddData[] = +{ + /**/ + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 20, 80, 66, 10, 32, + 2, 40, 161, 133, 20, + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + /**/ + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 244, 80, 66, 10, 32, + 3, 40, 161, 133, 20, + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + /**/ + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 247, 80, 66, 10, 32, + 3, 232, 161, 133, 20, + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + /**/ + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 247, 208, 66, 10, 32, + 3, 239, 161, 133, 20, + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + /**/ + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 247, 223, 66, 10, 32, + 3, 239, 161, 133, 20, + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + /**/ + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 247, 223, 66, 10, 32, + 3, 239, 191, 133, 20, + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + /**/ + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 247, 223, 126, 10, 32, + 3, 239, 191, 133, 20, + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + /**/ + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 247, 223, 126, 10, 32, + 3, 239, 191, 253, 20, + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + /**/ + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 247, 223, 126, 250, 32, + 3, 239, 191, 253, 20, + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + /**/ + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 32, + 3, 239, 191, 253, 244, + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + /**/ + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, +}; + +//////////////////////////////////////////////////////////////////////////////// + + +class MovieCart +{ + +public: + + MovieCart(); + ~MovieCart(); + + bool init(const std::string& path); + bool process(uint16_t address); + + uint8_t + readROM(uint16_t address) + { + return myROM[address & 1023]; + } + + void + writeROM(uint16_t address, uint8_t data) + { + myROM[address & 1023] = data; + } + +private: + + enum Mode + { + Volume, + Bright, + Time, + Last = Time + }; + + enum TitleState + { + Display, + Exiting, + Stream + }; + + + void stopTitleScreen(); + + void writeColor(uint16_t address); + void writeAudioData(uint16_t address, uint8_t val); + void writeAudio(uint16_t address); + void writeGraph(uint16_t address); + + void runStateMachine(); + + void fill_addr_right_line(); + void fill_addr_left_line(bool again); + void fill_addr_end_lines(); + void fill_addr_blank_lines(); + + void updateTransport(); + + + StreamReader myStream; + + // data + + uint8_t myROM[1024]; + + + // title screen state + int myTitleCycles; + uint8_t myTitleState; + + + // address info + bool myA7; + bool myA10; + uint8_t myA10_Count; + + // state machine info + + uint8_t myState; + bool myPlaying; + bool myOdd; + bool myBufferIndex; + + + uint8_t myLines; + int32_t myFrameNumber; // signed + + uint8_t myMode; + uint8_t myBright; + uint8_t myForceColor; + + // expressed in frames + uint8_t myDrawLevelBars; + uint8_t myDrawTimeCode; + + MovieInputs myInputs; + MovieInputs myLastInputs; + + int8_t mySpeed; // signed + uint8_t myJoyRepeat; + uint8_t myDirectionValue; + uint8_t myButtonsValue; + + uint8_t myVolume; + const uint8_t* myVolumeScale; + uint8_t myFirstAudioVal; + +}; + + +MovieCart::MovieCart() +{ +} + +MovieCart::~MovieCart() +{ +} + +bool +MovieCart::init(const std::string& path) +{ + memcpy(myROM, kernelROM, 1024); + + myTitleCycles = 0; + myTitleState = TitleState::Display; + + myA7 = false; + myA10 = false; + myA10_Count = 0; + + myState = 3; + myPlaying = true; + myOdd = true; + myBufferIndex = false; + myFrameNumber = 1; + + myInputs.init(); + myLastInputs.init(); + mySpeed = 1; + myJoyRepeat = 0; + myDirectionValue = 0; + myButtonsValue = 0; + + myLines = 0; + myForceColor = 0; + myDrawLevelBars = 0; + myDrawTimeCode = 0; + myFirstAudioVal = 0; + + myMode = Mode::Volume; + myVolume = DEFAULT_LEVEL; + myVolumeScale = scales[DEFAULT_LEVEL]; + myBright = DEFAULT_LEVEL; + + if (!myStream.open(path)) + return false; + + myStream.swapField(true); + + return true; +} + +void +MovieCart::stopTitleScreen() +{ + writeROM(addr_title_loop + 0, 0x18); // clear carry, one bit difference from 0x38 sec +} + + +void +MovieCart::writeColor(uint16_t address) +{ + uint8_t v = myStream.readColor(); + v = (v & 0xf0) | shiftBright[(v & 0x0f) + myBright]; + + if (myForceColor) + v = myForceColor; + if (myInputs.bw) + v &= 0x0f; + + writeROM(address, v); +} + +void +MovieCart::writeAudioData(uint16_t address, uint8_t val) +{ + uint8_t v; + v = myVolumeScale[val]; + writeROM(address, v); +} + +void +MovieCart::writeAudio(uint16_t address) +{ + uint8_t v = myStream.readAudio(); + writeAudioData(address, v); +} + +void +MovieCart::writeGraph(uint16_t address) +{ + uint8_t v = myStream.readGraph(); + writeROM(address, v); +} + +void +MovieCart::updateTransport() +{ + myStream.overrideGraph(nullptr); + + + // have to cut rate in half, to remove glitches...todo.. + { + if (myBufferIndex == true) + { + uint8_t temp = ~(myA10_Count & 0x1e) & 0x1e; + + if (temp == myDirectionValue) + myInputs.updateDirection(temp); + + myDirectionValue = temp; + } + else + { + uint8_t temp = ~(myA10_Count & 0x17) & 0x17; + + if (temp == myButtonsValue) + myInputs.updateTransport(temp); + + myButtonsValue = temp; + } + + myA10_Count = 0; + } + + if (myInputs.reset) + { + myFrameNumber = 1; + myPlaying = true; + myDrawTimeCode = OSD_FRAMES; + + goto update_stream; + } + + uint8_t lastMainMode = myMode; + + if (myInputs.up && !myLastInputs.up) + { + if (myMode == 0) + myMode = Mode::Last; + else + myMode--; + } + else if (myInputs.down && !myLastInputs.down) + { + if (myMode == Mode::Last) + myMode = 0; + else + myMode++; + } + + if (myInputs.left || myInputs.right) + { + myJoyRepeat++; + } + else + { + myJoyRepeat = 0; + mySpeed = 1; + } + + + if (myJoyRepeat & 16) + { + myJoyRepeat = 0; + + if (myInputs.left || myInputs.right) + { + if (myMode == Mode::Time) + { + myDrawTimeCode = OSD_FRAMES; + mySpeed += 4; + if (mySpeed < 0) + mySpeed -= 4; + } + else if (myMode == Mode::Volume) + { + myDrawLevelBars = OSD_FRAMES; + if (myInputs.left) + { + if (myVolume) + myVolume--; + } + else + { + myVolume++; + if (myVolume >= MAX_LEVEL) + myVolume--; + } + } + else if (myMode == Mode::Bright) + { + myDrawLevelBars = OSD_FRAMES; + if (myInputs.left) + { + if (myBright) + myBright--; + } + else + { + myBright++; + if (myBright >= MAX_LEVEL) + myBright--; + } + } + } + } + + + if (myInputs.select && !myLastInputs.select) + { + myDrawTimeCode = OSD_FRAMES; + myFrameNumber -= 60 * BACK_SECONDS + 1; + goto update_stream; + } + + if (myInputs.fire && !myLastInputs.fire) + myPlaying = !myPlaying; + + switch (myMode) + { + case Mode::Time: + if (lastMainMode != myMode) + myDrawTimeCode = OSD_FRAMES; + break; + + case Mode::Bright: + case Mode::Volume: + default: + if (lastMainMode != myMode) + myDrawLevelBars = OSD_FRAMES; + break; + } + + // just draw one + if (myDrawLevelBars > myDrawTimeCode) + myDrawTimeCode = 0; + else + myDrawLevelBars = 0; + + if (myPlaying) + myVolumeScale = scales[myVolume]; + else + myVolumeScale = scales[0]; + + // update frame + + int8_t step = 1; + + if (!myPlaying) // step while paused + { + if (myMode == Mode::Time) + { + if (myInputs.right && !myLastInputs.right) + step = 3; + else if (myInputs.left && !myLastInputs.left) + step = -3; + else + step = (myFrameNumber & 1) ? -1 : 1; + } + else + { + step = (myFrameNumber & 1) ? -1 : 1; + } + } + else + { + if (myMode == Mode::Time) + { + if (myInputs.right) + step = mySpeed; + else if (myInputs.left) + step = -mySpeed; + } + else + { + step = 1; + } + } + + myFrameNumber += step; + if (myFrameNumber < 1) + { + myFrameNumber = 1; + mySpeed = 1; + } + +update_stream: + + myLastInputs = myInputs; + +} + +void +MovieCart::fill_addr_right_line() +{ + writeGraph(addr_right_line + 9); // #GDATA0 + writeGraph(addr_right_line + 13); // #GDATA1 + writeGraph(addr_right_line + 17); // #GDATA2 + writeGraph(addr_right_line + 21); // #GDATA3 + writeGraph(addr_right_line + 23); // #GDATA4 + + writeColor(addr_right_line + 25); // #GCOL0 + writeColor(addr_right_line + 29); // #GCOL1 + writeColor(addr_right_line + 35); // #GCOL2 + writeColor(addr_right_line + 43); // #GCOL3 + writeColor(addr_right_line + 47); // #GCOL4 +} + +void +MovieCart::fill_addr_left_line(bool again) +{ + writeAudio(addr_left_line + 5); // #AUD_DATA + + writeGraph(addr_left_line + 15); // #GDATA5 + writeGraph(addr_left_line + 19); // #GDATA6 + writeGraph(addr_left_line + 23); // #GDATA7 + writeGraph(addr_left_line + 27); // #GDATA8 + writeGraph(addr_left_line + 29); // #GDATA9 + + writeColor(addr_left_line + 31); // #GCOL5 + writeColor(addr_left_line + 35); // #GCOL6 + writeColor(addr_left_line + 41); // #GCOL7 + writeColor(addr_left_line + 49); // #GCOL8 + writeColor(addr_left_line + 53); // #GCOL9 + + writeAudio(addr_left_line + 57); // #AUD_DATA + + // addr_pick_line_end = 0x0ee; + // jmp right_line + // jmp end_lines + if (again) + { + writeROM(addr_pick_continue + 1, LO_JUMP_BYTE(addr_right_line)); + writeROM(addr_pick_continue + 2, HI_JUMP_BYTE(addr_right_line)); + } + else + { + writeROM(addr_pick_continue + 1, LO_JUMP_BYTE(addr_end_lines)); + writeROM(addr_pick_continue + 2, HI_JUMP_BYTE(addr_end_lines)); + } +} + + +void +MovieCart::fill_addr_end_lines() +{ + writeAudio(addr_end_lines_audio + 1); + myFirstAudioVal = myStream.peekAudio(); + + // normally overscan=28, vblank=37 + // todo: clicky noise.. + if (myOdd) + { + writeROM(addr_set_overscan_size + 1, 28); + writeROM(addr_set_vblank_size + 1, 36); + } + else + { + writeROM(addr_set_overscan_size + 1, 29); + writeROM(addr_set_vblank_size + 1, 37); + } + + if (myBufferIndex == false) + { + writeROM(addr_pick_transport + 1, LO_JUMP_BYTE(addr_transport_direction)); + writeROM(addr_pick_transport + 2, HI_JUMP_BYTE(addr_transport_direction)); + } + else + { + writeROM(addr_pick_transport + 1, LO_JUMP_BYTE(addr_transport_buttons)); + writeROM(addr_pick_transport + 2, HI_JUMP_BYTE(addr_transport_buttons)); + } + +} + +void +MovieCart::fill_addr_blank_lines() +{ + uint8_t i; + uint8_t v; + + // version number + myStream.readVersion(); + myStream.readVersion(); + myStream.readVersion(); + myStream.readVersion(); + + // frame number + myStream.readFrame(); + myStream.readFrame(); + v = myStream.readFrame(); + + // make sure we're in sync with frame data + myOdd = (v & 1); + + // 28 overscan + // 3 vsync + // 37 vblank + + if (myOdd) + { + writeAudioData(addr_audio_bank + 0, myFirstAudioVal); + for (i = 1; i < (BLANK_LINE_SIZE + 1); i++) + writeAudio(addr_audio_bank + i); + } + else + { + for (i = 0; i < (BLANK_LINE_SIZE -1); i++) + writeAudio(addr_audio_bank + i); + } + + writeAudio(addr_last_audio + 1); +} + +void +MovieCart::runStateMachine() +{ + switch(myState) + { + case 1: + if (myA7) + { + if (myLines == (TIMECODE_HEIGHT-1)) + { + if (myDrawTimeCode) + { + myDrawTimeCode--; + myForceColor = COLOR_BLUE; + myStream.startTimeCode(); + } + } + + // label = 12, bars = 7 + if (myLines == 21) + { + if (myDrawLevelBars) + { + myDrawLevelBars--; + myForceColor = COLOR_BLUE; + + switch (myMode) + { + case Mode::Time: + myStream.overrideGraph(nullptr); + break; + + case Mode::Bright: + if (myOdd) + myStream.overrideGraph(brightLabelOdd); + else + myStream.overrideGraph(brightLabelEven); + break; + + case Mode::Volume: + default: + if (myOdd) + myStream.overrideGraph(volumeLabelOdd); + else + myStream.overrideGraph(volumeLabelEven); + break; + } + } + } + + if (myLines == 7) + { + if (myDrawLevelBars) + { + uint8_t levelValue; + + switch (myMode) + { + case Mode::Time: + levelValue = 0; + break; + + case Mode::Bright: + levelValue = myBright; + break; + + case Mode::Volume: + default: + levelValue = myVolume; + break; + } + + if (myOdd) + myStream.overrideGraph(&levelBarsOddData[levelValue * 40]); + else + myStream.overrideGraph(&levelBarsEvenData[levelValue * 40]); + } + } + + fill_addr_right_line(); + + myLines -= 1; + myState = 2; + } + break; + + + case 2: + if (!myA7) + { + if (myLines >= 1) + { + fill_addr_left_line(1); + + myLines -= 1; + myState = 1; + } + else + { + fill_addr_left_line(0); + fill_addr_end_lines(); + + myStream.swapField(myBufferIndex); + myBufferIndex = !myBufferIndex; + updateTransport(); + + fill_addr_blank_lines(); + + myState = 3; + } + } + break; + + case 3: + if (myA7) + { + // hit end? rewind just before end + while (myFrameNumber >= 2 && !myStream.readField(myFrameNumber, myBufferIndex)) + { + myFrameNumber -= 2; + myJoyRepeat = 0; + } + + myForceColor = 0; + myLines = 191; + myState = 1; + } + break; + + default: + break; + } +} + +bool +MovieCart::process(uint16_t address) +{ + + bool a12 = (address & (1 << 12)) ? 1:0; + bool a11 = (address & (1 << 11)) ? 1:0; + + // count a10 pulses + bool a10i = (address & (1 << 10)); + if (a10i && !myA10) + myA10_Count++; + myA10 = a10i; + + // latch a7 state + if (a11) // a12 + myA7 = (address & (1 << 7)); // each 128 + + switch(myTitleState) + { + case TitleState::Display: + myTitleCycles++; + if (myTitleCycles == TITLE_CYCLES) + { + stopTitleScreen(); + myTitleState = TitleState::Exiting; + myTitleCycles = 0; + } + break; + + case TitleState::Exiting: + if (myA7) + myTitleState = TitleState::Stream; + break; + + case TitleState::Stream: + runStateMachine(); + break; + } + + return a12; +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CartridgeMVC::CartridgeMVC(const string& path, size_t size, const string& md5, const Settings& settings, @@ -25,6 +1410,7 @@ CartridgeMVC::CartridgeMVC(const string& path, size_t size, : Cartridge(settings, md5) { myPath = path; + myMovie = make_unique(); // not used mySize = 1024; @@ -51,7 +1437,7 @@ void CartridgeMVC::install(System& system) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CartridgeMVC::reset() { - myMovie.init(myPath); + myMovie->init(myPath); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -65,20 +1451,20 @@ const ByteBuffer& CartridgeMVC::getImage(size_t& size) const // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool CartridgeMVC::patch(uInt16 address, uInt8 value) { - myMovie.writeROM(address, value); + myMovie->writeROM(address, value); return true; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - uInt8 CartridgeMVC::peek(uInt16 address) { - myMovie.process(address); - return myMovie.readROM(address); + myMovie->process(address); + return myMovie->readROM(address); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool CartridgeMVC::poke(uInt16 address, uInt8 value) { - return myMovie.process(address); + return myMovie->process(address); } diff --git a/src/emucore/CartMVC.hxx b/src/emucore/CartMVC.hxx index 025940f44..2a4cf246f 100755 --- a/src/emucore/CartMVC.hxx +++ b/src/emucore/CartMVC.hxx @@ -19,10 +19,10 @@ #define CARTRIDGEMVC_HXX class System; +class MovieCart; #include "bspf.hxx" #include "Cart.hxx" -#include "MovieCart/MovieCart.hxx" /** Implementation of MovieCart. @@ -33,6 +33,10 @@ class System; @author Rob Bairos */ + +#define MVC_FIELD_SIZE 2560 // round field to nearest 512 byte boundary +#define MVC_FIELD_PAD_SIZE 4096 // round to nearest 4K + class CartridgeMVC : public Cartridge { @@ -173,8 +177,8 @@ class CartridgeMVC : public Cartridge private: - MovieCart myMovie; - string myPath; + unique_ptr myMovie; + string myPath; }; diff --git a/src/emucore/MovieCart/KernelData.hxx b/src/emucore/MovieCart/KernelData.hxx deleted file mode 100755 index 6eae1f952..000000000 --- a/src/emucore/MovieCart/KernelData.hxx +++ /dev/null @@ -1,421 +0,0 @@ -//============================================================================ -// -// SSSS tt lll lll -// SS SS tt ll ll -// SS tttttt eeee ll ll aaaa -// SSSS tt ee ee ll ll aa -// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" -// SS SS tt ee ll ll aa aa -// SSSS ttt eeeee llll llll aaaaa -// -// Copyright (c) 1995-2021 by Bradford W. Mott, Stephen Anthony -// and the Stella Team -// -// See the file "License.txt" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -//============================================================================ -// Key kernel positions, automatically generated - -/** - Various kernel, OSD and scale definitions - @author Rob Bairos -*/ - -#pragma once - -#include - -#define TIMECODE_HEIGHT 12 -#define MAX_LEVEL 11 -#define DEFAULT_LEVEL 6 -#define BLANK_LINE_SIZE (28+3+37) // 68 - -#define addr_kernel_48 0x800 -#define addr_transport_buttons 0x880 -#define addr_transport_direction 0x897 -#define addr_right_line 0x94c -#define addr_left_line 0x980 -#define addr_pick_continue 0x9c2 -#define addr_main_start 0xa00 -#define addr_aud_bank_setup 0xa0c -#define addr_tg0 0xa24 -#define addr_title_again 0xa3b -#define addr_end_lines 0xa80 -#define addr_end_lines_audio 0xaa1 -#define addr_set_overscan_size 0xaad -#define addr_set_vblank_size 0xac3 -#define addr_pick_transport 0xacc -#define addr_last_audio 0xacf -#define addr_wait_lines 0xad4 -#define addr_transport_done1 0xae7 -#define addr_draw_title 0xb00 -#define addr_title_loop 0xb50 -#define addr_black_bar 0xb52 -#define addr_animate_bar1 0xb58 -#define addr_animate_bar_again1 0xb5a -#define addr_animate_dex1 0xb65 -#define addr_audio_bank 0xb80 -#define addr_reset_loop 0xbfa - -// scale adjustments, automatically generated -const uint8_t scale0[16] = { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}; /* 0.0000 */ -const uint8_t scale1[16] = { 6, 6, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 9, 9}; /* 0.1667 */ -const uint8_t scale2[16] = { 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10}; /* 0.3333 */ -const uint8_t scale3[16] = { 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11}; /* 0.5000 */ -const uint8_t scale4[16] = { 3, 3, 4, 5, 5, 6, 7, 7, 8, 9, 9, 10, 11, 11, 12, 13}; /* 0.6667 */ -const uint8_t scale5[16] = { 1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 10, 10, 11, 12, 13, 14}; /* 0.8333 */ -const uint8_t scale6[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; /* 1.0000 */ -const uint8_t scale7[16] = { 0, 0, 0, 1, 3, 4, 5, 7, 8, 10, 11, 12, 14, 15, 15, 15}; /* 1.3611 */ -const uint8_t scale8[16] = { 0, 0, 0, 0, 1, 3, 5, 7, 8, 10, 12, 14, 15, 15, 15, 15}; /* 1.7778 */ -const uint8_t scale9[16] = { 0, 0, 0, 0, 0, 2, 4, 6, 9, 11, 13, 15, 15, 15, 15, 15}; /* 2.2500 */ -const uint8_t scale10[16] = { 0, 0, 0, 0, 0, 1, 3, 6, 9, 12, 14, 15, 15, 15, 15, 15}; /* 2.7778 */ -const uint8_t *scales[11] = {scale0, scale1, scale2, scale3, scale4, scale5, scale6, scale7, scale8, scale9, scale10}; - -// lower bit is ignored anyways -const uint8_t shiftBright[16 + MAX_LEVEL - 1] = { 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 15, 15, 15, 15}; - -// Compiled kernel -const unsigned char kernelROM[] = -{ - 133, 2, 185, 50, 248, 133, 27, 185, 62, 248, 133, 28, 185, 74, 248, 133, - 27, 185, 86, 248, 133, 135, 185, 98, 248, 190, 110, 248, 132, 136, 164, 135, - 132, 28, 133, 27, 134, 28, 134, 27, 164, 136, 102, 137, 176, 210, 136, 16, - 207, 96, 0, 1, 1, 1, 0, 0, 48, 48, 50, 53, 56, 48, 249, 129, - 129, 128, 248, 0, 99, 102, 102, 102, 230, 99, 140, 252, 140, 136, 112, 0, - 192, 97, 99, 102, 102, 198, 198, 198, 248, 198, 248, 0, 193, 32, 48, 24, - 24, 25, 24, 24, 24, 24, 126, 0, 249, 97, 97, 97, 97, 249, 0, 0, - 0, 0, 0, 0, 248, 128, 128, 224, 128, 248, 255, 255, 255, 255, 255, 255, - 165, 12, 10, 173, 130, 2, 42, 41, 23, 133, 129, 133, 128, 133, 128, 133, - 128, 133, 128, 133, 128, 234, 96, 173, 128, 2, 74, 74, 74, 133, 129, 133, - 128, 133, 128, 133, 128, 133, 128, 133, 128, 133, 128, 234, 96, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 133, 25, 133, 128, - 134, 32, 134, 33, 169, 243, 133, 27, 169, 207, 133, 28, 169, 251, 133, 27, - 169, 239, 162, 191, 160, 66, 133, 28, 169, 54, 133, 6, 134, 27, 169, 238, - 133, 7, 132, 6, 132, 28, 169, 182, 133, 6, 169, 114, 133, 7, 133, 42, - 162, 0, 162, 0, 169, 0, 162, 128, 133, 25, 134, 32, 134, 33, 169, 231, - 133, 27, 169, 159, 133, 28, 169, 253, 133, 27, 169, 247, 162, 223, 160, 242, - 133, 28, 169, 248, 133, 6, 134, 27, 169, 172, 133, 7, 132, 6, 132, 28, - 169, 216, 133, 6, 169, 98, 133, 7, 169, 0, 162, 0, 162, 0, 162, 0, - 133, 42, 76, 76, 249, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 120, 216, 162, 255, 154, 169, 0, 149, 0, 202, 208, 251, 169, 128, 133, 130, - 169, 251, 133, 131, 169, 1, 133, 37, 133, 38, 169, 3, 133, 4, 133, 5, - 133, 2, 162, 4, 133, 128, 202, 208, 251, 133, 128, 133, 16, 133, 17, 169, - 208, 133, 32, 169, 224, 133, 33, 133, 2, 133, 42, 165, 132, 106, 106, 133, - 6, 133, 7, 169, 85, 133, 137, 32, 0, 251, 176, 239, 169, 0, 133, 9, - 141, 129, 2, 141, 131, 2, 169, 6, 133, 4, 169, 2, 133, 5, 169, 0, - 133, 2, 133, 128, 76, 128, 250, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 133, 25, 169, 0, 133, 27, 133, 28, 133, 27, 133, 28, 133, 128, 133, 128, - 133, 128, 169, 0, 133, 16, 234, 133, 17, 169, 208, 133, 32, 169, 192, 133, - 33, 169, 0, 133, 2, 133, 42, 133, 128, 133, 25, 160, 0, 162, 28, 32, - 212, 250, 169, 2, 133, 0, 162, 3, 32, 212, 250, 169, 0, 133, 0, 169, - 2, 133, 1, 162, 37, 32, 212, 250, 162, 0, 134, 1, 32, 128, 248, 169, - 0, 76, 76, 249, 177, 130, 133, 2, 133, 128, 133, 128, 133, 25, 165, 129, - 240, 5, 198, 129, 173, 128, 20, 200, 202, 208, 233, 96, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 162, 30, 32, 82, 251, 169, 2, 133, 0, 162, 3, 32, 82, 251, 169, 0, - 133, 0, 169, 2, 133, 1, 162, 37, 32, 82, 251, 169, 0, 133, 1, 198, - 132, 165, 132, 133, 133, 160, 255, 162, 30, 32, 88, 251, 162, 54, 32, 82, - 251, 160, 11, 32, 0, 248, 169, 0, 133, 27, 133, 28, 133, 27, 133, 28, - 162, 54, 32, 82, 251, 165, 132, 133, 133, 160, 1, 162, 30, 32, 88, 251, - 56, 96, 169, 0, 133, 133, 160, 0, 132, 134, 24, 165, 133, 101, 134, 133, - 133, 133, 2, 133, 9, 202, 208, 242, 96, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 250, 0, 250, 0, 250, -}; - -// OSD labels - -const uint8_t brightLabelEven[] = -{ - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 225, 48, 12, 252, - 6, 140, 231, 96, 0, - 0, 113, 48, 12, 96, - 6, 140, 192, 96, 0, - 0, 225, 49, 15, 96, - 6, 152, 195, 96, 0, - 0, 49, 48, 12, 96, - 6, 140, 231, 96, 0, - 0, 225, 48, 12, 96, -}; - -const uint8_t brightLabelOdd[] = -{ - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 7, 252, 126, 99, 0, - 0, 113, 48, 12, 96, - 6, 140, 192, 96, 0, - 0, 97, 49, 12, 96, - 7, 248, 223, 224, 0, - 0, 113, 49, 12, 96, - 6, 156, 195, 96, 0, - 0, 113, 48, 12, 96, - 7, 142, 127, 96, 0, - 0, 0, 0, 0, 0 -}; - -const uint8_t volumeLabelEven[] = -{ - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 199, 192, 14, 254, - 113, 112, 99, 112, 0, - 0, 140, 192, 14, 192, - 51, 48, 99, 240, 0, - 0, 28, 192, 15, 254, - 31, 48, 99, 240, 0, - 0, 12, 192, 15, 192, - 30, 112, 119, 176, 0, - 0, 7, 252, 12, 254, -}; - -const uint8_t volumeLabelOdd[] = -{ - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 97, 224, 99, 112, 0, - 0, 142, 192, 14, 192, - 51, 112, 99, 112, 0, - 0, 28, 192, 15, 192, - 59, 48, 99, 240, 0, - 0, 28, 192, 15, 192, - 30, 112, 99, 176, 0, - 0, 14, 192, 13, 192, - 14, 224, 62, 48, 0, - 0, 0, 0, 0, 0 -}; - -// Level bars -// 8 rows * 5 columns = 40 - -const uint8_t levelBarsEvenData[] = -{ - /**/ - 0, 0, 0, 0, 0, - 3, 239, 191, 253, 247, - 247, 223, 126, 251, 224, - 2, 40, 161, 133, 20, - 20, 80, 66, 10, 32, - 3, 239, 191, 253, 247, - 247, 223, 126, 251, 224, - 0, 0, 0, 0, 0, - /**/ - 0, 0, 0, 0, 0, - 3, 239, 191, 253, 247, - 247, 223, 126, 251, 224, - 3, 40, 161, 133, 20, - 244, 80, 66, 10, 32, - 3, 239, 191, 253, 247, - 247, 223, 126, 251, 224, - 0, 0, 0, 0, 0, - /**/ - 0, 0, 0, 0, 0, - 3, 239, 191, 253, 247, - 247, 223, 126, 251, 224, - 3, 232, 161, 133, 20, - 247, 80, 66, 10, 32, - 3, 239, 191, 253, 247, - 247, 223, 126, 251, 224, - 0, 0, 0, 0, 0, - /**/ - 0, 0, 0, 0, 0, - 3, 239, 191, 253, 247, - 247, 223, 126, 251, 224, - 3, 239, 161, 133, 20, - 247, 208, 66, 10, 32, - 3, 239, 191, 253, 247, - 247, 223, 126, 251, 224, - 0, 0, 0, 0, 0, - /**/ - 0, 0, 0, 0, 0, - 3, 239, 191, 253, 247, - 247, 223, 126, 251, 224, - 3, 239, 161, 133, 20, - 247, 223, 66, 10, 32, - 3, 239, 191, 253, 247, - 247, 223, 126, 251, 224, - 0, 0, 0, 0, 0, - /**/ - 0, 0, 0, 0, 0, - 3, 239, 191, 253, 247, - 247, 223, 126, 251, 224, - 3, 239, 191, 133, 20, - 247, 223, 66, 10, 32, - 3, 239, 191, 253, 247, - 247, 223, 126, 251, 224, - 0, 0, 0, 0, 0, - /**/ - 0, 0, 0, 0, 0, - 3, 239, 191, 253, 247, - 247, 223, 126, 251, 224, - 3, 239, 191, 133, 20, - 247, 223, 126, 10, 32, - 3, 239, 191, 253, 247, - 247, 223, 126, 251, 224, - 0, 0, 0, 0, 0, - /**/ - 0, 0, 0, 0, 0, - 3, 239, 191, 253, 247, - 247, 223, 126, 251, 224, - 3, 239, 191, 253, 20, - 247, 223, 126, 10, 32, - 3, 239, 191, 253, 247, - 247, 223, 126, 251, 224, - 0, 0, 0, 0, 0, - /**/ - 0, 0, 0, 0, 0, - 3, 239, 191, 253, 247, - 247, 223, 126, 251, 224, - 3, 239, 191, 253, 20, - 247, 223, 126, 250, 32, - 3, 239, 191, 253, 247, - 247, 223, 126, 251, 224, - 0, 0, 0, 0, 0, - /**/ - 0, 0, 0, 0, 0, - 3, 239, 191, 253, 247, - 247, 223, 126, 251, 224, - 3, 239, 191, 253, 244, - 247, 223, 126, 251, 32, - 3, 239, 191, 253, 247, - 247, 223, 126, 251, 224, - 0, 0, 0, 0, 0, - /**/ - 0, 0, 0, 0, 0, - 3, 239, 191, 253, 247, - 247, 223, 126, 251, 224, - 3, 239, 191, 253, 247, - 247, 223, 126, 251, 224, - 3, 239, 191, 253, 247, - 247, 223, 126, 251, 224, - 0, 0, 0, 0, 0, - -}; - -const uint8_t levelBarsOddData[] = -{ - /**/ - 247, 223, 126, 251, 224, - 3, 239, 191, 253, 247, - 20, 80, 66, 10, 32, - 2, 40, 161, 133, 20, - 247, 223, 126, 251, 224, - 3, 239, 191, 253, 247, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - /**/ - 247, 223, 126, 251, 224, - 3, 239, 191, 253, 247, - 244, 80, 66, 10, 32, - 3, 40, 161, 133, 20, - 247, 223, 126, 251, 224, - 3, 239, 191, 253, 247, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - /**/ - 247, 223, 126, 251, 224, - 3, 239, 191, 253, 247, - 247, 80, 66, 10, 32, - 3, 232, 161, 133, 20, - 247, 223, 126, 251, 224, - 3, 239, 191, 253, 247, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - /**/ - 247, 223, 126, 251, 224, - 3, 239, 191, 253, 247, - 247, 208, 66, 10, 32, - 3, 239, 161, 133, 20, - 247, 223, 126, 251, 224, - 3, 239, 191, 253, 247, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - /**/ - 247, 223, 126, 251, 224, - 3, 239, 191, 253, 247, - 247, 223, 66, 10, 32, - 3, 239, 161, 133, 20, - 247, 223, 126, 251, 224, - 3, 239, 191, 253, 247, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - /**/ - 247, 223, 126, 251, 224, - 3, 239, 191, 253, 247, - 247, 223, 66, 10, 32, - 3, 239, 191, 133, 20, - 247, 223, 126, 251, 224, - 3, 239, 191, 253, 247, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - /**/ - 247, 223, 126, 251, 224, - 3, 239, 191, 253, 247, - 247, 223, 126, 10, 32, - 3, 239, 191, 133, 20, - 247, 223, 126, 251, 224, - 3, 239, 191, 253, 247, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - /**/ - 247, 223, 126, 251, 224, - 3, 239, 191, 253, 247, - 247, 223, 126, 10, 32, - 3, 239, 191, 253, 20, - 247, 223, 126, 251, 224, - 3, 239, 191, 253, 247, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - /**/ - 247, 223, 126, 251, 224, - 3, 239, 191, 253, 247, - 247, 223, 126, 250, 32, - 3, 239, 191, 253, 20, - 247, 223, 126, 251, 224, - 3, 239, 191, 253, 247, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - /**/ - 247, 223, 126, 251, 224, - 3, 239, 191, 253, 247, - 247, 223, 126, 251, 32, - 3, 239, 191, 253, 244, - 247, 223, 126, 251, 224, - 3, 239, 191, 253, 247, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - /**/ - 247, 223, 126, 251, 224, - 3, 239, 191, 253, 247, - 247, 223, 126, 251, 224, - 3, 239, 191, 253, 247, - 247, 223, 126, 251, 224, - 3, 239, 191, 253, 247, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, -}; - diff --git a/src/emucore/MovieCart/MovieCart.cxx b/src/emucore/MovieCart/MovieCart.cxx deleted file mode 100755 index c30b65482..000000000 --- a/src/emucore/MovieCart/MovieCart.cxx +++ /dev/null @@ -1,626 +0,0 @@ -//============================================================================ -// -// SSSS tt lll lll -// SS SS tt ll ll -// SS tttttt eeee ll ll aaaa -// SSSS tt ee ee ll ll aa -// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" -// SS SS tt ee ll ll aa aa -// SSSS ttt eeeee llll llll aaaaa -// -// Copyright (c) 1995-2021 by Bradford W. Mott, Stephen Anthony -// and the Stella Team -// -// See the file "License.txt" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -//============================================================================ -// Key kernel positions, automatically generated - -/** - Implementation of MovieCart. - 1K of memory is presented on the bus, but is repeated to fill the 4K image space. - Contents are dynamically altered with streaming image and audio content as specific - 128-byte regions are entered. - Original implementation: github.com/lodefmode/moviecart - - @author Rob Bairos -*/ - -#include -#include "KernelData.hxx" -#include "MovieCart.hxx" - -#define LO_JUMP_BYTE(X) ((X) & 0xff) -#define HI_JUMP_BYTE(X) ((((X) & 0xff00) >> 8) | 0x10) - -#define COLOR_BLUE 0x9A -#define COLOR_WHITE 0x0E - -#define OSD_FRAMES 180 -#define BACK_SECONDS 10 - -#define TITLE_CYCLES 1000000 - -bool -MovieCart::init(const std::string& path) -{ - memcpy(myROM, kernelROM, 1024); - - myTitleCycles = 0; - myTitleState = TitleState::Display; - - myA7 = false; - myA10 = false; - myA10_Count = 0; - - myState = 3; - myPlaying = true; - myOdd = true; - myBufferIndex = false; - myFrameNumber = 1; - - myInputs.init(); - myLastInputs.init(); - mySpeed = 1; - myJoyRepeat = 0; - myDirectionValue = 0; - myButtonsValue = 0; - - myLines = 0; - myForceColor = 0; - myDrawLevelBars = 0; - myDrawTimeCode = 0; - myFirstAudioVal = 0; - - myMode = Mode::Volume; - myVolume = DEFAULT_LEVEL; - myVolumeScale = scales[DEFAULT_LEVEL]; - myBright = DEFAULT_LEVEL; - - if (!myStream.open(path)) - return false; - - myStream.swapField(true); - - return true; -} - -void -MovieCart::stopTitleScreen() -{ - writeROM(addr_title_loop + 0, 0x18); // clear carry, one bit difference from 0x38 sec -} - - -void -MovieCart::writeColor(uint16_t address) -{ - uint8_t v = myStream.readColor(); - v = (v & 0xf0) | shiftBright[(v & 0x0f) + myBright]; - - if (myForceColor) - v = myForceColor; - if (myInputs.bw) - v &= 0x0f; - - writeROM(address, v); -} - -void -MovieCart::writeAudioData(uint16_t address, uint8_t val) -{ - uint8_t v; - v = myVolumeScale[val]; - writeROM(address, v); -} - -void -MovieCart::writeAudio(uint16_t address) -{ - uint8_t v = myStream.readAudio(); - writeAudioData(address, v); -} - -void -MovieCart::writeGraph(uint16_t address) -{ - uint8_t v = myStream.readGraph(); - writeROM(address, v); -} - -void -MovieCart::updateTransport() -{ - myStream.overrideGraph(nullptr); - - - // have to cut rate in half, to remove glitches...todo.. - { - if (myBufferIndex == true) - { - uint8_t temp = ~(myA10_Count & 0x1e) & 0x1e; - - if (temp == myDirectionValue) - myInputs.updateDirection(temp); - - myDirectionValue = temp; - } - else - { - uint8_t temp = ~(myA10_Count & 0x17) & 0x17; - - if (temp == myButtonsValue) - myInputs.updateTransport(temp); - - myButtonsValue = temp; - } - - myA10_Count = 0; - } - - if (myInputs.reset) - { - myFrameNumber = 1; - myPlaying = true; - myDrawTimeCode = OSD_FRAMES; - - goto update_stream; - } - - uint8_t lastMainMode = myMode; - - if (myInputs.up && !myLastInputs.up) - { - if (myMode == 0) - myMode = Mode::Last; - else - myMode--; - } - else if (myInputs.down && !myLastInputs.down) - { - if (myMode == Mode::Last) - myMode = 0; - else - myMode++; - } - - if (myInputs.left || myInputs.right) - { - myJoyRepeat++; - } - else - { - myJoyRepeat = 0; - mySpeed = 1; - } - - - if (myJoyRepeat & 16) - { - myJoyRepeat = 0; - - if (myInputs.left || myInputs.right) - { - if (myMode == Mode::Time) - { - myDrawTimeCode = OSD_FRAMES; - mySpeed += 4; - if (mySpeed < 0) - mySpeed -= 4; - } - else if (myMode == Mode::Volume) - { - myDrawLevelBars = OSD_FRAMES; - if (myInputs.left) - { - if (myVolume) - myVolume--; - } - else - { - myVolume++; - if (myVolume >= MAX_LEVEL) - myVolume--; - } - } - else if (myMode == Mode::Bright) - { - myDrawLevelBars = OSD_FRAMES; - if (myInputs.left) - { - if (myBright) - myBright--; - } - else - { - myBright++; - if (myBright >= MAX_LEVEL) - myBright--; - } - } - } - } - - - if (myInputs.select && !myLastInputs.select) - { - myDrawTimeCode = OSD_FRAMES; - myFrameNumber -= 60 * BACK_SECONDS + 1; - goto update_stream; - } - - if (myInputs.fire && !myLastInputs.fire) - myPlaying = !myPlaying; - - switch (myMode) - { - case Mode::Time: - if (lastMainMode != myMode) - myDrawTimeCode = OSD_FRAMES; - break; - - case Mode::Bright: - case Mode::Volume: - default: - if (lastMainMode != myMode) - myDrawLevelBars = OSD_FRAMES; - break; - } - - // just draw one - if (myDrawLevelBars > myDrawTimeCode) - myDrawTimeCode = 0; - else - myDrawLevelBars = 0; - - if (myPlaying) - myVolumeScale = scales[myVolume]; - else - myVolumeScale = scales[0]; - - // update frame - - int8_t step = 1; - - if (!myPlaying) // step while paused - { - if (myMode == Mode::Time) - { - if (myInputs.right && !myLastInputs.right) - step = 3; - else if (myInputs.left && !myLastInputs.left) - step = -3; - else - step = (myFrameNumber & 1) ? -1 : 1; - } - else - { - step = (myFrameNumber & 1) ? -1 : 1; - } - } - else - { - if (myMode == Mode::Time) - { - if (myInputs.right) - step = mySpeed; - else if (myInputs.left) - step = -mySpeed; - } - else - { - step = 1; - } - } - - myFrameNumber += step; - if (myFrameNumber < 1) - { - myFrameNumber = 1; - mySpeed = 1; - } - -update_stream: - - myLastInputs = myInputs; - -} - -void -MovieCart::fill_addr_right_line() -{ - writeGraph(addr_right_line + 9); // #GDATA0 - writeGraph(addr_right_line + 13); // #GDATA1 - writeGraph(addr_right_line + 17); // #GDATA2 - writeGraph(addr_right_line + 21); // #GDATA3 - writeGraph(addr_right_line + 23); // #GDATA4 - - writeColor(addr_right_line + 25); // #GCOL0 - writeColor(addr_right_line + 29); // #GCOL1 - writeColor(addr_right_line + 35); // #GCOL2 - writeColor(addr_right_line + 43); // #GCOL3 - writeColor(addr_right_line + 47); // #GCOL4 -} - -void -MovieCart::fill_addr_left_line(bool again) -{ - writeAudio(addr_left_line + 5); // #AUD_DATA - - writeGraph(addr_left_line + 15); // #GDATA5 - writeGraph(addr_left_line + 19); // #GDATA6 - writeGraph(addr_left_line + 23); // #GDATA7 - writeGraph(addr_left_line + 27); // #GDATA8 - writeGraph(addr_left_line + 29); // #GDATA9 - - writeColor(addr_left_line + 31); // #GCOL5 - writeColor(addr_left_line + 35); // #GCOL6 - writeColor(addr_left_line + 41); // #GCOL7 - writeColor(addr_left_line + 49); // #GCOL8 - writeColor(addr_left_line + 53); // #GCOL9 - - writeAudio(addr_left_line + 57); // #AUD_DATA - - // addr_pick_line_end = 0x0ee; - // jmp right_line - // jmp end_lines - if (again) - { - writeROM(addr_pick_continue + 1, LO_JUMP_BYTE(addr_right_line)); - writeROM(addr_pick_continue + 2, HI_JUMP_BYTE(addr_right_line)); - } - else - { - writeROM(addr_pick_continue + 1, LO_JUMP_BYTE(addr_end_lines)); - writeROM(addr_pick_continue + 2, HI_JUMP_BYTE(addr_end_lines)); - } -} - - -void -MovieCart::fill_addr_end_lines() -{ - writeAudio(addr_end_lines_audio + 1); - myFirstAudioVal = myStream.peekAudio(); - - // normally overscan=28, vblank=37 - // todo: clicky noise.. - if (myOdd) - { - writeROM(addr_set_overscan_size + 1, 28); - writeROM(addr_set_vblank_size + 1, 36); - } - else - { - writeROM(addr_set_overscan_size + 1, 29); - writeROM(addr_set_vblank_size + 1, 37); - } - - if (myBufferIndex == false) - { - writeROM(addr_pick_transport + 1, LO_JUMP_BYTE(addr_transport_direction)); - writeROM(addr_pick_transport + 2, HI_JUMP_BYTE(addr_transport_direction)); - } - else - { - writeROM(addr_pick_transport + 1, LO_JUMP_BYTE(addr_transport_buttons)); - writeROM(addr_pick_transport + 2, HI_JUMP_BYTE(addr_transport_buttons)); - } - -} - -void -MovieCart::fill_addr_blank_lines() -{ - uint8_t i; - uint8_t v; - - // version number - myStream.readVersion(); - myStream.readVersion(); - myStream.readVersion(); - myStream.readVersion(); - - // frame number - myStream.readFrame(); - myStream.readFrame(); - v = myStream.readFrame(); - - // make sure we're in sync with frame data - myOdd = (v & 1); - - // 28 overscan - // 3 vsync - // 37 vblank - - if (myOdd) - { - writeAudioData(addr_audio_bank + 0, myFirstAudioVal); - for (i = 1; i < (BLANK_LINE_SIZE + 1); i++) - writeAudio(addr_audio_bank + i); - } - else - { - for (i = 0; i < (BLANK_LINE_SIZE -1); i++) - writeAudio(addr_audio_bank + i); - } - - writeAudio(addr_last_audio + 1); -} - -void -MovieCart::runStateMachine() -{ - switch(myState) - { - case 1: - if (myA7) - { - if (myLines == (TIMECODE_HEIGHT-1)) - { - if (myDrawTimeCode) - { - myDrawTimeCode--; - myForceColor = COLOR_BLUE; - myStream.startTimeCode(); - } - } - - // label = 12, bars = 7 - if (myLines == 21) - { - if (myDrawLevelBars) - { - myDrawLevelBars--; - myForceColor = COLOR_BLUE; - - switch (myMode) - { - case Mode::Time: - myStream.overrideGraph(nullptr); - break; - - case Mode::Bright: - if (myOdd) - myStream.overrideGraph(brightLabelOdd); - else - myStream.overrideGraph(brightLabelEven); - break; - - case Mode::Volume: - default: - if (myOdd) - myStream.overrideGraph(volumeLabelOdd); - else - myStream.overrideGraph(volumeLabelEven); - break; - } - } - } - - if (myLines == 7) - { - if (myDrawLevelBars) - { - uint8_t levelValue; - - switch (myMode) - { - case Mode::Time: - levelValue = 0; - break; - - case Mode::Bright: - levelValue = myBright; - break; - - case Mode::Volume: - default: - levelValue = myVolume; - break; - } - - if (myOdd) - myStream.overrideGraph(&levelBarsOddData[levelValue * 40]); - else - myStream.overrideGraph(&levelBarsEvenData[levelValue * 40]); - } - } - - fill_addr_right_line(); - - myLines -= 1; - myState = 2; - } - break; - - - case 2: - if (!myA7) - { - if (myLines >= 1) - { - fill_addr_left_line(1); - - myLines -= 1; - myState = 1; - } - else - { - fill_addr_left_line(0); - fill_addr_end_lines(); - - myStream.swapField(myBufferIndex); - myBufferIndex = !myBufferIndex; - updateTransport(); - - fill_addr_blank_lines(); - - myState = 3; - } - } - break; - - case 3: - if (myA7) - { - // hit end? rewind just before end - while (myFrameNumber >= 2 && !myStream.readField(myFrameNumber, myBufferIndex)) - { - myFrameNumber -= 2; - myJoyRepeat = 0; - } - - myForceColor = 0; - myLines = 191; - myState = 1; - } - break; - - default: - break; - } -} - -bool -MovieCart::process(uint16_t address) -{ - - bool a12 = (address & (1 << 12)) ? 1:0; - bool a11 = (address & (1 << 11)) ? 1:0; - - // count a10 pulses - bool a10i = (address & (1 << 10)); - if (a10i && !myA10) - myA10_Count++; - myA10 = a10i; - - // latch a7 state - if (a11) // a12 - myA7 = (address & (1 << 7)); // each 128 - - switch(myTitleState) - { - case TitleState::Display: - myTitleCycles++; - if (myTitleCycles == TITLE_CYCLES) - { - stopTitleScreen(); - myTitleState = TitleState::Exiting; - myTitleCycles = 0; - } - break; - - case TitleState::Exiting: - if (myA7) - myTitleState = TitleState::Stream; - break; - - case TitleState::Stream: - runStateMachine(); - break; - } - - return a12; -} - diff --git a/src/emucore/MovieCart/MovieCart.hxx b/src/emucore/MovieCart/MovieCart.hxx deleted file mode 100755 index b58c1c0db..000000000 --- a/src/emucore/MovieCart/MovieCart.hxx +++ /dev/null @@ -1,147 +0,0 @@ -//============================================================================ -// -// SSSS tt lll lll -// SS SS tt ll ll -// SS tttttt eeee ll ll aaaa -// SSSS tt ee ee ll ll aa -// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" -// SS SS tt ee ll ll aa aa -// SSSS ttt eeeee llll llll aaaaa -// -// Copyright (c) 1995-2021 by Bradford W. Mott, Stephen Anthony -// and the Stella Team -// -// See the file "License.txt" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -//============================================================================ -// Key kernel positions, automatically generated - -/** - Implementation of MovieCart. - 1K of memory is presented on the bus, but is repeated to fill the 4K image space. - Contents are dynamically altered with streaming image and audio content as specific - 128-byte regions are entered. - Original implementation: github.com/lodefmode/moviecart - - @author Rob Bairos -*/ - -#pragma once - -#include -#include "StreamReader.hxx" -#include "MovieInputs.hxx" - -class MovieCart -{ - -public: - - MovieCart() - { - } - - ~MovieCart() - { - } - - bool init(const std::string& path); - bool process(uint16_t address); - - uint8_t - readROM(uint16_t address) - { - return myROM[address & 1023]; - } - - void - writeROM(uint16_t address, uint8_t data) - { - myROM[address & 1023] = data; - } - -private: - - enum Mode - { - Volume, - Bright, - Time, - Last = Time - }; - - enum TitleState - { - Display, - Exiting, - Stream - }; - - - void stopTitleScreen(); - - void writeColor(uint16_t address); - void writeAudioData(uint16_t address, uint8_t val); - void writeAudio(uint16_t address); - void writeGraph(uint16_t address); - - void runStateMachine(); - - void fill_addr_right_line(); - void fill_addr_left_line(bool again); - void fill_addr_end_lines(); - void fill_addr_blank_lines(); - - void updateTransport(); - - - StreamReader myStream; - - // data - - uint8_t myROM[1024]; - - - // title screen state - int myTitleCycles; - uint8_t myTitleState; - - - // address info - bool myA7; - bool myA10; - uint8_t myA10_Count; - - // state machine info - - uint8_t myState; - bool myPlaying; - bool myOdd; - bool myBufferIndex; - - - uint8_t myLines; - int32_t myFrameNumber; // signed - - uint8_t myMode; - uint8_t myBright; - uint8_t myForceColor; - - // expressed in frames - uint8_t myDrawLevelBars; - uint8_t myDrawTimeCode; - - MovieInputs myInputs; - MovieInputs myLastInputs; - int8_t mySpeed; // signed - uint8_t myJoyRepeat; - uint8_t myDirectionValue; - uint8_t myButtonsValue; - - uint8_t myVolume; - const uint8_t* myVolumeScale; - uint8_t myFirstAudioVal; - -}; - - diff --git a/src/emucore/MovieCart/MovieInputs.hxx b/src/emucore/MovieCart/MovieInputs.hxx deleted file mode 100755 index 20c31f0e5..000000000 --- a/src/emucore/MovieCart/MovieInputs.hxx +++ /dev/null @@ -1,91 +0,0 @@ -//============================================================================ -// -// SSSS tt lll lll -// SS SS tt ll ll -// SS tttttt eeee ll ll aaaa -// SSSS tt ee ee ll ll aa -// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" -// SS SS tt ee ll ll aa aa -// SSSS ttt eeeee llll llll aaaaa -// -// Copyright (c) 1995-2021 by Bradford W. Mott, Stephen Anthony -// and the Stella Team -// -// See the file "License.txt" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -//============================================================================ -// Key kernel positions, automatically generated - -/** - State of current switches and joystick positions to control MovieCart - @author Rob Bairos -*/ - -#pragma once - -class MovieInputs -{ -public: - - MovieInputs() - { - init(); - } - - void - init() - { - bw = false; - fire = false; - select = false; - reset = false; - - right = false; - left = false; - up = false; - down = false; - } - - bool bw; - bool fire; - bool select; - bool reset; - - bool right; - bool left; - bool up; - bool down; - - void - updateDirection(uint8_t val) - { - right = val & TRANSPORT_RIGHT; - left = val & TRANSPORT_LEFT; - up = val & TRANSPORT_UP; - down = val & TRANSPORT_DOWN; - } - - void updateTransport(uint8_t val) - { - bw = val & TRANSPORT_BW; - fire = val & TRANSPORT_BUTTON; - select = val & TRANSPORT_SELECT; - reset = val & TRANSPORT_RESET; - } - -private: - - static int constexpr TRANSPORT_RIGHT = 0x10; - static int constexpr TRANSPORT_LEFT = 0x08; - static int constexpr TRANSPORT_DOWN = 0x04; - static int constexpr TRANSPORT_UP = 0x02; - static int constexpr TRANSPORT_UNUSED1 = 0x01; // Right-2 - - static int constexpr TRANSPORT_BW = 0x10; - static int constexpr TRANSPORT_UNUSED2 = 0x08; - static int constexpr TRANSPORT_SELECT = 0x04; - static int constexpr TRANSPORT_RESET = 0x02; - static int constexpr TRANSPORT_BUTTON = 0x01; - -}; - diff --git a/src/emucore/MovieCart/StreamReader.cxx b/src/emucore/MovieCart/StreamReader.cxx deleted file mode 100755 index 9029b5858..000000000 --- a/src/emucore/MovieCart/StreamReader.cxx +++ /dev/null @@ -1,96 +0,0 @@ -//============================================================================ -// -// SSSS tt lll lll -// SS SS tt ll ll -// SS tttttt eeee ll ll aaaa -// SSSS tt ee ee ll ll aa -// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" -// SS SS tt ee ll ll aa aa -// SSSS ttt eeeee llll llll aaaaa -// -// Copyright (c) 1995-2021 by Bradford W. Mott, Stephen Anthony -// and the Stella Team -// -// See the file "License.txt" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -//============================================================================ -// Key kernel positions, automatically generated - -/** - Simulate retrieval of 512 byte chunks from a serial source - @author Rob Bairos -*/ - -#include "StreamReader.hxx" - -bool -StreamReader::open(const std::string& path) -{ - close(); - - myFile = new std::ifstream(path, std::ios::binary); - - if (!myFile || !*myFile) - close(); - - myFile->seekg(0, std::ios::end); - myFileSize = static_cast(myFile->tellg()); - myFile->seekg(0, std::ios::beg); - - return myFile ? true:false; -} - -void -StreamReader::close() -{ - delete myFile; - myFile = nullptr; -} - -void -StreamReader::swapField(bool index) -{ - if (index == true) - { - myVersion = myBuffer1 + VERSION_DATA_OFFSET; - myFrame = myBuffer1 + FRAME_DATA_OFFSET; - myAudio = myBuffer1 + AUDIO_DATA_OFFSET; - myGraph = myBuffer1 + GRAPH_DATA_OFFSET; - myTimecode= myBuffer1 + TIMECODE_DATA_OFFSET; - myColor = myBuffer1 + COLOR_DATA_OFFSET; - } - else - { - myVersion = myBuffer2 + VERSION_DATA_OFFSET; - myFrame = myBuffer2 + FRAME_DATA_OFFSET; - myAudio = myBuffer2 + AUDIO_DATA_OFFSET; - myGraph = myBuffer2 + GRAPH_DATA_OFFSET; - myTimecode = myBuffer2 + TIMECODE_DATA_OFFSET; - myColor = myBuffer2 + COLOR_DATA_OFFSET; - } -} - -bool -StreamReader::readField(uint32_t fnum, bool index) -{ - bool read = false; - - if (myFile) - { - size_t offset = ((fnum + 0) * MVC_FIELD_PAD_SIZE); - - if (offset + MVC_FIELD_PAD_SIZE < myFileSize) - { - myFile->seekg(offset); - if (index == true) - myFile->read((char*)myBuffer1, MVC_FIELD_SIZE); - else - myFile->read((char*)myBuffer2, MVC_FIELD_SIZE); - - read = true; - } - } - - return read; -} - diff --git a/src/emucore/MovieCart/StreamReader.hxx b/src/emucore/MovieCart/StreamReader.hxx deleted file mode 100755 index 61a0b33e1..000000000 --- a/src/emucore/MovieCart/StreamReader.hxx +++ /dev/null @@ -1,135 +0,0 @@ -//============================================================================ -// -// SSSS tt lll lll -// SS SS tt ll ll -// SS tttttt eeee ll ll aaaa -// SSSS tt ee ee ll ll aa -// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" -// SS SS tt ee ll ll aa aa -// SSSS ttt eeeee llll llll aaaaa -// -// Copyright (c) 1995-2021 by Bradford W. Mott, Stephen Anthony -// and the Stella Team -// -// See the file "License.txt" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -//============================================================================ -// Key kernel positions, automatically generated - -/** - Simulate retrieval 512 byte chunks from a serial source - @author Rob Bairos -*/ - -#pragma once - -#include -#include -#include - -#define MVC_FIELD_SIZE 2560 // round field to nearest 512 byte boundary -#define MVC_FIELD_PAD_SIZE 4096 // round to nearest 4K - -class StreamReader -{ -public: - - StreamReader() - { - } - - ~StreamReader() - { - close(); - } - - bool open(const std::string& path); - void close(); - void swapField(bool index); - bool readField(uint32_t fnum, bool index); - - uint8_t - readVersion() - { - return *myVersion++; - } - - uint8_t - readFrame() - { - return *myFrame++; - } - - uint8_t - readColor() - { - return *myColor++; - } - - uint8_t - readGraph() - { - uint8_t v; - - if (myGraphOverride) - v = *myGraphOverride++; - else - v = *myGraph++; - - return v; - } - - void - overrideGraph(const uint8_t* p) - { - myGraphOverride = p; - } - - uint8_t - readAudio() - { - return *myAudio++; - } - - uint8_t - peekAudio() - { - return *myAudio; - } - - void - startTimeCode() - { - myGraph = myTimecode; - } - - -private: - - static int constexpr VERSION_DATA_OFFSET = 0; - static int constexpr FRAME_DATA_OFFSET = 4; - static int constexpr AUDIO_DATA_OFFSET = 7; - static int constexpr GRAPH_DATA_OFFSET = 269; - static int constexpr TIMECODE_DATA_OFFSET = 1229; - static int constexpr COLOR_DATA_OFFSET = 1289; - static int constexpr END_DATA_OFFSET = 2249; - - - const uint8_t* myAudio{nullptr}; - - const uint8_t* myGraph{nullptr}; - const uint8_t* myGraphOverride{nullptr}; - - const uint8_t* myTimecode{nullptr}; - const uint8_t* myColor{nullptr}; - const uint8_t* myVersion{nullptr}; - const uint8_t* myFrame{nullptr}; - - uint8_t myBuffer1[MVC_FIELD_SIZE]; - uint8_t myBuffer2[MVC_FIELD_SIZE]; - - std::ifstream* myFile{nullptr}; - size_t myFileSize{0}; - -}; - diff --git a/src/windows/Stella.vcxproj b/src/windows/Stella.vcxproj old mode 100644 new mode 100755 index 1d890a299..376fd915e --- a/src/windows/Stella.vcxproj +++ b/src/windows/Stella.vcxproj @@ -764,8 +764,6 @@ - - @@ -1837,10 +1835,6 @@ - - - - diff --git a/src/windows/Stella.vcxproj.filters b/src/windows/Stella.vcxproj.filters index 67c3394df..8aa5465db 100644 --- a/src/windows/Stella.vcxproj.filters +++ b/src/windows/Stella.vcxproj.filters @@ -1113,12 +1113,6 @@ Source Files\emucore - - Source Files\emucore - - - Source Files\emucore - @@ -2294,18 +2288,6 @@ Header Files\emucore - - Header Files\emucore - - - Header Files\emucore - - - Header Files\emucore - - - Header Files\emucore - From ed07f642cd49eda020c79938fcc48f6dd5a7f7b4 Mon Sep 17 00:00:00 2001 From: Stephen Anthony Date: Wed, 21 Apr 2021 22:13:38 -0230 Subject: [PATCH 04/17] Some cleanups for moviecart code. - Compiles in Linux now, and without any warnings or errors - Converted some code to use that already in Stella - Formatting cleanups to match Stella style --- src/emucore/CartDetector.cxx | 6 +- src/emucore/CartMVC.cxx | 2101 ++++++++++++++++------------------ src/emucore/CartMVC.hxx | 71 +- src/emucore/Serializer.cxx | 8 + src/emucore/Serializer.hxx | 12 +- src/emucore/module.mk | 1 + 6 files changed, 1036 insertions(+), 1163 deletions(-) mode change 100755 => 100644 src/emucore/CartMVC.cxx mode change 100755 => 100644 src/emucore/CartMVC.hxx diff --git a/src/emucore/CartDetector.cxx b/src/emucore/CartDetector.cxx index a0765622d..3414d5be9 100644 --- a/src/emucore/CartDetector.cxx +++ b/src/emucore/CartDetector.cxx @@ -456,7 +456,7 @@ bool CartDetector::isProbablyCDF(const ByteBuffer& image, size_t size) // 0x10adab1e (LOADABLE) if needed for future improvement uInt8 cdf[] = { 'C', 'D', 'F' }; uInt8 cdfjplus[] = { 'P', 'L', 'U', 'S', 'C', 'D', 'F', 'J' }; - return (searchForBytes(image, size, cdf, 3, 3) || + return (searchForBytes(image, size, cdf, 3, 3) || searchForBytes(image, size, cdfjplus, 8, 1)); } @@ -704,11 +704,11 @@ bool CartDetector::isProbablyMVC(const ByteBuffer& image, size_t size) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - size_t CartDetector::isProbablyMVC(std::istream &in, size_t maxSize) { - const size_t frameSize = 2 * MVC_FIELD_PAD_SIZE; + const size_t frameSize = 2 * CartridgeMVC::MVC_FIELD_PAD_SIZE; bool found = false; // Returns size of field if stream is probably an MVC movie cartridge - + if (maxSize >= frameSize) { auto pos = in.tellg(); diff --git a/src/emucore/CartMVC.cxx b/src/emucore/CartMVC.cxx old mode 100755 new mode 100644 index f30c4393e..b1884b8a0 --- a/src/emucore/CartMVC.cxx +++ b/src/emucore/CartMVC.cxx @@ -15,10 +15,10 @@ // this file, and for a DISCLAIMER OF ALL WARRANTIES. //============================================================================ +#include "Serializer.hxx" #include "System.hxx" #include "CartMVC.hxx" - /** Implementation of MovieCart. 1K of memory is presented on the bus, but is repeated to fill the 4K image space. @@ -29,785 +29,689 @@ @author Rob Bairos */ -#include -#include -#include -#include - #define LO_JUMP_BYTE(X) ((X) & 0xff) #define HI_JUMP_BYTE(X) ((((X) & 0xff00) >> 8) | 0x10) -#define COLOR_BLUE 0x9A -#define COLOR_WHITE 0x0E +#define COLOR_BLUE 0x9A +// #define COLOR_WHITE 0x0E -#define OSD_FRAMES 180 -#define BACK_SECONDS 10 +#define OSD_FRAMES 180 +#define BACK_SECONDS 10 -#define TITLE_CYCLES 1000000 +#define TITLE_CYCLES 1000000 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /** Simulate retrieval 512 byte chunks from a serial source */ - class StreamReader { -public: + public: + StreamReader() = default; - StreamReader() - { - } + bool open(const string& path) { + myFile = Serializer(path, Serializer::Mode::ReadOnly); + if(myFile) + myFileSize = myFile.size(); - ~StreamReader() - { - close(); - } + return bool(myFile); + } - bool open(const std::string& path); - void close(); - void swapField(bool index); - bool readField(uint32_t fnum, bool index); + void swapField(bool index) { + if(index) + { + myVersion = myBuffer1 + VERSION_DATA_OFFSET; + myFrame = myBuffer1 + FRAME_DATA_OFFSET; + myAudio = myBuffer1 + AUDIO_DATA_OFFSET; + myGraph = myBuffer1 + GRAPH_DATA_OFFSET; + myTimecode= myBuffer1 + TIMECODE_DATA_OFFSET; + myColor = myBuffer1 + COLOR_DATA_OFFSET; + } + else + { + myVersion = myBuffer2 + VERSION_DATA_OFFSET; + myFrame = myBuffer2 + FRAME_DATA_OFFSET; + myAudio = myBuffer2 + AUDIO_DATA_OFFSET; + myGraph = myBuffer2 + GRAPH_DATA_OFFSET; + myTimecode = myBuffer2 + TIMECODE_DATA_OFFSET; + myColor = myBuffer2 + COLOR_DATA_OFFSET; + } + } - uint8_t - readVersion() - { - return *myVersion++; - } + bool readField(uInt32 fnum, bool index) { + if(myFile) + { + size_t offset = ((fnum + 0) * CartridgeMVC::MVC_FIELD_PAD_SIZE); - uint8_t - readFrame() - { - return *myFrame++; - } + if(offset + CartridgeMVC::MVC_FIELD_PAD_SIZE < myFileSize) + { + myFile.setPosition(offset); + if(index) + myFile.getByteArray(myBuffer1, CartridgeMVC::MVC_FIELD_SIZE); + else + myFile.getByteArray(myBuffer2, CartridgeMVC::MVC_FIELD_SIZE); - uint8_t - readColor() - { - return *myColor++; - } + return true; + } + } + return false; + } - uint8_t - readGraph() - { - uint8_t v; + uInt8 readVersion() { return *myVersion++; } + uInt8 readFrame() { return *myFrame++; } + uInt8 readColor() { return *myColor++; } - if (myGraphOverride) - v = *myGraphOverride++; - else - v = *myGraph++; + uInt8 readGraph() { + return myGraphOverride ? *myGraphOverride++ : *myGraph++; + } - return v; - } + void overrideGraph(const uInt8* p) { + myGraphOverride = p; + } - void - overrideGraph(const uint8_t* p) - { - myGraphOverride = p; - } + uInt8 readAudio() { return *myAudio++; } - uint8_t - readAudio() - { - return *myAudio++; - } + uInt8 peekAudio() const { return *myAudio; } - uint8_t - peekAudio() - { - return *myAudio; - } + void startTimeCode() { myGraph = myTimecode; } - void - startTimeCode() - { - myGraph = myTimecode; - } + private: + static constexpr int + VERSION_DATA_OFFSET = 0, + FRAME_DATA_OFFSET = 4, + AUDIO_DATA_OFFSET = 7, + GRAPH_DATA_OFFSET = 269, + TIMECODE_DATA_OFFSET = 1229, + COLOR_DATA_OFFSET = 1289, + END_DATA_OFFSET = 2249; + const uInt8* myAudio{nullptr}; -private: + const uInt8* myGraph{nullptr}; + const uInt8* myGraphOverride{nullptr}; - static int constexpr VERSION_DATA_OFFSET = 0; - static int constexpr FRAME_DATA_OFFSET = 4; - static int constexpr AUDIO_DATA_OFFSET = 7; - static int constexpr GRAPH_DATA_OFFSET = 269; - static int constexpr TIMECODE_DATA_OFFSET = 1229; - static int constexpr COLOR_DATA_OFFSET = 1289; - static int constexpr END_DATA_OFFSET = 2249; + const uInt8* myTimecode{nullptr}; + const uInt8* myColor{nullptr}; + const uInt8* myVersion{nullptr}; + const uInt8* myFrame{nullptr}; + uInt8 myBuffer1[CartridgeMVC::MVC_FIELD_SIZE]; + uInt8 myBuffer2[CartridgeMVC::MVC_FIELD_SIZE]; - const uint8_t* myAudio{nullptr}; - - const uint8_t* myGraph{nullptr}; - const uint8_t* myGraphOverride{nullptr}; - - const uint8_t* myTimecode{nullptr}; - const uint8_t* myColor{nullptr}; - const uint8_t* myVersion{nullptr}; - const uint8_t* myFrame{nullptr}; - - uint8_t myBuffer1[MVC_FIELD_SIZE]; - uint8_t myBuffer2[MVC_FIELD_SIZE]; - - std::ifstream* myFile{nullptr}; - size_t myFileSize{0}; - + Serializer myFile; + size_t myFileSize{0}; }; -bool -StreamReader::open(const std::string& path) -{ - close(); - - myFile = new std::ifstream(path, std::ios::binary); - - if (!myFile || !*myFile) - close(); - - myFile->seekg(0, std::ios::end); - myFileSize = static_cast(myFile->tellg()); - myFile->seekg(0, std::ios::beg); - - return myFile ? true:false; -} - -void -StreamReader::close() -{ - delete myFile; - myFile = nullptr; -} - -void -StreamReader::swapField(bool index) -{ - if (index == true) - { - myVersion = myBuffer1 + VERSION_DATA_OFFSET; - myFrame = myBuffer1 + FRAME_DATA_OFFSET; - myAudio = myBuffer1 + AUDIO_DATA_OFFSET; - myGraph = myBuffer1 + GRAPH_DATA_OFFSET; - myTimecode= myBuffer1 + TIMECODE_DATA_OFFSET; - myColor = myBuffer1 + COLOR_DATA_OFFSET; - } - else - { - myVersion = myBuffer2 + VERSION_DATA_OFFSET; - myFrame = myBuffer2 + FRAME_DATA_OFFSET; - myAudio = myBuffer2 + AUDIO_DATA_OFFSET; - myGraph = myBuffer2 + GRAPH_DATA_OFFSET; - myTimecode = myBuffer2 + TIMECODE_DATA_OFFSET; - myColor = myBuffer2 + COLOR_DATA_OFFSET; - } -} - -bool -StreamReader::readField(uint32_t fnum, bool index) -{ - bool read = false; - - if (myFile) - { - size_t offset = ((fnum + 0) * MVC_FIELD_PAD_SIZE); - - if (offset + MVC_FIELD_PAD_SIZE < myFileSize) - { - myFile->seekg(offset); - if (index == true) - myFile->read((char*)myBuffer1, MVC_FIELD_SIZE); - else - myFile->read((char*)myBuffer2, MVC_FIELD_SIZE); - - read = true; - } - } - - return read; -} - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /** State of current switches and joystick positions to control MovieCart */ - class MovieInputs { -public: + public: + MovieInputs() = default; - MovieInputs() - { - init(); - } + void init() { + bw = fire = select = reset = false; + right = left = up = down = false; + } - void - init() - { - bw = false; - fire = false; - select = false; - reset = false; + bool bw{false}, fire{false}, select{false}, reset{false}; + bool right{false}, left{false}, up{false}, down{false}; - right = false; - left = false; - up = false; - down = false; - } + void updateDirection(uInt8 val) { + right = val & TRANSPORT_RIGHT; + left = val & TRANSPORT_LEFT; + up = val & TRANSPORT_UP; + down = val & TRANSPORT_DOWN; + } - bool bw; - bool fire; - bool select; - bool reset; + void updateTransport(uInt8 val) { + bw = val & TRANSPORT_BW; + fire = val & TRANSPORT_BUTTON; + select = val & TRANSPORT_SELECT; + reset = val & TRANSPORT_RESET; + } - bool right; - bool left; - bool up; - bool down; + private: + static constexpr uInt8 + TRANSPORT_RIGHT = 0x10, + TRANSPORT_LEFT = 0x08, + TRANSPORT_DOWN = 0x04, + TRANSPORT_UP = 0x02, + TRANSPORT_UNUSED1 = 0x01; // Right-2 - void - updateDirection(uint8_t val) - { - right = val & TRANSPORT_RIGHT; - left = val & TRANSPORT_LEFT; - up = val & TRANSPORT_UP; - down = val & TRANSPORT_DOWN; - } - - void updateTransport(uint8_t val) - { - bw = val & TRANSPORT_BW; - fire = val & TRANSPORT_BUTTON; - select = val & TRANSPORT_SELECT; - reset = val & TRANSPORT_RESET; - } - -private: - - static int constexpr TRANSPORT_RIGHT = 0x10; - static int constexpr TRANSPORT_LEFT = 0x08; - static int constexpr TRANSPORT_DOWN = 0x04; - static int constexpr TRANSPORT_UP = 0x02; - static int constexpr TRANSPORT_UNUSED1 = 0x01; // Right-2 - - static int constexpr TRANSPORT_BW = 0x10; - static int constexpr TRANSPORT_UNUSED2 = 0x08; - static int constexpr TRANSPORT_SELECT = 0x04; - static int constexpr TRANSPORT_RESET = 0x02; - static int constexpr TRANSPORT_BUTTON = 0x01; - -}; + static constexpr uInt8 + TRANSPORT_BW = 0x10, + TRANSPORT_UNUSED2 = 0x08, + TRANSPORT_SELECT = 0x04, + TRANSPORT_RESET = 0x02, + TRANSPORT_BUTTON = 0x01; + }; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /** Various kernel, OSD and scale definitions @author Rob Bairos */ - #define TIMECODE_HEIGHT 12 #define MAX_LEVEL 11 #define DEFAULT_LEVEL 6 -#define BLANK_LINE_SIZE (28+3+37) // 68 +#define BLANK_LINE_SIZE (28+3+37) // 68 -#define addr_kernel_48 0x800 +// #define addr_kernel_48 0x800 #define addr_transport_buttons 0x880 #define addr_transport_direction 0x897 #define addr_right_line 0x94c #define addr_left_line 0x980 #define addr_pick_continue 0x9c2 -#define addr_main_start 0xa00 -#define addr_aud_bank_setup 0xa0c -#define addr_tg0 0xa24 -#define addr_title_again 0xa3b +// #define addr_main_start 0xa00 +// #define addr_aud_bank_setup 0xa0c +// #define addr_tg0 0xa24 +// #define addr_title_again 0xa3b #define addr_end_lines 0xa80 #define addr_end_lines_audio 0xaa1 #define addr_set_overscan_size 0xaad #define addr_set_vblank_size 0xac3 #define addr_pick_transport 0xacc #define addr_last_audio 0xacf -#define addr_wait_lines 0xad4 -#define addr_transport_done1 0xae7 -#define addr_draw_title 0xb00 +// #define addr_wait_lines 0xad4 +// #define addr_transport_done1 0xae7 +// #define addr_draw_title 0xb00 #define addr_title_loop 0xb50 -#define addr_black_bar 0xb52 -#define addr_animate_bar1 0xb58 -#define addr_animate_bar_again1 0xb5a -#define addr_animate_dex1 0xb65 +// #define addr_black_bar 0xb52 +// #define addr_animate_bar1 0xb58 +// #define addr_animate_bar_again1 0xb5a +// #define addr_animate_dex1 0xb65 #define addr_audio_bank 0xb80 -#define addr_reset_loop 0xbfa +// #define addr_reset_loop 0xbfa // scale adjustments, automatically generated -const uint8_t scale0[16] = { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}; /* 0.0000 */ -const uint8_t scale1[16] = { 6, 6, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 9, 9}; /* 0.1667 */ -const uint8_t scale2[16] = { 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10}; /* 0.3333 */ -const uint8_t scale3[16] = { 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11}; /* 0.5000 */ -const uint8_t scale4[16] = { 3, 3, 4, 5, 5, 6, 7, 7, 8, 9, 9, 10, 11, 11, 12, 13}; /* 0.6667 */ -const uint8_t scale5[16] = { 1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 10, 10, 11, 12, 13, 14}; /* 0.8333 */ -const uint8_t scale6[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; /* 1.0000 */ -const uint8_t scale7[16] = { 0, 0, 0, 1, 3, 4, 5, 7, 8, 10, 11, 12, 14, 15, 15, 15}; /* 1.3611 */ -const uint8_t scale8[16] = { 0, 0, 0, 0, 1, 3, 5, 7, 8, 10, 12, 14, 15, 15, 15, 15}; /* 1.7778 */ -const uint8_t scale9[16] = { 0, 0, 0, 0, 0, 2, 4, 6, 9, 11, 13, 15, 15, 15, 15, 15}; /* 2.2500 */ -const uint8_t scale10[16] = { 0, 0, 0, 0, 0, 1, 3, 6, 9, 12, 14, 15, 15, 15, 15, 15}; /* 2.7778 */ -const uint8_t *scales[11] = {scale0, scale1, scale2, scale3, scale4, scale5, scale6, scale7, scale8, scale9, scale10}; +static constexpr uInt8 scale0[16] = { + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 /* 0.0000 */ +}; +static constexpr uInt8 scale1[16] = { + 6, 6, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 9, 9 /* 0.1667 */ +}; +static constexpr uInt8 scale2[16] = { + 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10 /* 0.3333 */ +}; +static constexpr uInt8 scale3[16] = { + 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11 /* 0.5000 */ +}; +static constexpr uInt8 scale4[16] = { + 3, 3, 4, 5, 5, 6, 7, 7, 8, 9, 9, 10, 11, 11, 12, 13 /* 0.6667 */ +}; +static constexpr uInt8 scale5[16] = { + 1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 10, 10, 11, 12, 13, 14 /* 0.8333 */ +}; +static constexpr uInt8 scale6[16] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 /* 1.0000 */ +}; +static constexpr uInt8 scale7[16] = { + 0, 0, 0, 1, 3, 4, 5, 7, 8, 10, 11, 12, 14, 15, 15, 15 /* 1.3611 */ +}; +static constexpr uInt8 scale8[16] = { + 0, 0, 0, 0, 1, 3, 5, 7, 8, 10, 12, 14, 15, 15, 15, 15 /* 1.7778 */ +}; +static constexpr uInt8 scale9[16] = { + 0, 0, 0, 0, 0, 2, 4, 6, 9, 11, 13, 15, 15, 15, 15, 15 /* 2.2500 */ +}; +static constexpr uInt8 scale10[16] = { + 0, 0, 0, 0, 0, 1, 3, 6, 9, 12, 14, 15, 15, 15, 15, 15 /* 2.7778 */ +}; +static const uInt8* scales[11] = { + scale0, scale1, scale2, scale3, scale4, scale5, + scale6, scale7, scale8, scale9, scale10 +}; // lower bit is ignored anyways -const uint8_t shiftBright[16 + MAX_LEVEL - 1] = { 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 15, 15, 15, 15}; +static constexpr uInt8 shiftBright[16 + MAX_LEVEL - 1] = { + 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 14, 15, 15, 15, 15, 15 +}; // Compiled kernel -const unsigned char kernelROM[] = -{ - 133, 2, 185, 50, 248, 133, 27, 185, 62, 248, 133, 28, 185, 74, 248, 133, - 27, 185, 86, 248, 133, 135, 185, 98, 248, 190, 110, 248, 132, 136, 164, 135, - 132, 28, 133, 27, 134, 28, 134, 27, 164, 136, 102, 137, 176, 210, 136, 16, - 207, 96, 0, 1, 1, 1, 0, 0, 48, 48, 50, 53, 56, 48, 249, 129, - 129, 128, 248, 0, 99, 102, 102, 102, 230, 99, 140, 252, 140, 136, 112, 0, - 192, 97, 99, 102, 102, 198, 198, 198, 248, 198, 248, 0, 193, 32, 48, 24, - 24, 25, 24, 24, 24, 24, 126, 0, 249, 97, 97, 97, 97, 249, 0, 0, - 0, 0, 0, 0, 248, 128, 128, 224, 128, 248, 255, 255, 255, 255, 255, 255, - 165, 12, 10, 173, 130, 2, 42, 41, 23, 133, 129, 133, 128, 133, 128, 133, - 128, 133, 128, 133, 128, 234, 96, 173, 128, 2, 74, 74, 74, 133, 129, 133, - 128, 133, 128, 133, 128, 133, 128, 133, 128, 133, 128, 234, 96, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 133, 25, 133, 128, - 134, 32, 134, 33, 169, 243, 133, 27, 169, 207, 133, 28, 169, 251, 133, 27, - 169, 239, 162, 191, 160, 66, 133, 28, 169, 54, 133, 6, 134, 27, 169, 238, - 133, 7, 132, 6, 132, 28, 169, 182, 133, 6, 169, 114, 133, 7, 133, 42, - 162, 0, 162, 0, 169, 0, 162, 128, 133, 25, 134, 32, 134, 33, 169, 231, - 133, 27, 169, 159, 133, 28, 169, 253, 133, 27, 169, 247, 162, 223, 160, 242, - 133, 28, 169, 248, 133, 6, 134, 27, 169, 172, 133, 7, 132, 6, 132, 28, - 169, 216, 133, 6, 169, 98, 133, 7, 169, 0, 162, 0, 162, 0, 162, 0, - 133, 42, 76, 76, 249, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 120, 216, 162, 255, 154, 169, 0, 149, 0, 202, 208, 251, 169, 128, 133, 130, - 169, 251, 133, 131, 169, 1, 133, 37, 133, 38, 169, 3, 133, 4, 133, 5, - 133, 2, 162, 4, 133, 128, 202, 208, 251, 133, 128, 133, 16, 133, 17, 169, - 208, 133, 32, 169, 224, 133, 33, 133, 2, 133, 42, 165, 132, 106, 106, 133, - 6, 133, 7, 169, 85, 133, 137, 32, 0, 251, 176, 239, 169, 0, 133, 9, - 141, 129, 2, 141, 131, 2, 169, 6, 133, 4, 169, 2, 133, 5, 169, 0, - 133, 2, 133, 128, 76, 128, 250, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 133, 25, 169, 0, 133, 27, 133, 28, 133, 27, 133, 28, 133, 128, 133, 128, - 133, 128, 169, 0, 133, 16, 234, 133, 17, 169, 208, 133, 32, 169, 192, 133, - 33, 169, 0, 133, 2, 133, 42, 133, 128, 133, 25, 160, 0, 162, 28, 32, - 212, 250, 169, 2, 133, 0, 162, 3, 32, 212, 250, 169, 0, 133, 0, 169, - 2, 133, 1, 162, 37, 32, 212, 250, 162, 0, 134, 1, 32, 128, 248, 169, - 0, 76, 76, 249, 177, 130, 133, 2, 133, 128, 133, 128, 133, 25, 165, 129, - 240, 5, 198, 129, 173, 128, 20, 200, 202, 208, 233, 96, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 162, 30, 32, 82, 251, 169, 2, 133, 0, 162, 3, 32, 82, 251, 169, 0, - 133, 0, 169, 2, 133, 1, 162, 37, 32, 82, 251, 169, 0, 133, 1, 198, - 132, 165, 132, 133, 133, 160, 255, 162, 30, 32, 88, 251, 162, 54, 32, 82, - 251, 160, 11, 32, 0, 248, 169, 0, 133, 27, 133, 28, 133, 27, 133, 28, - 162, 54, 32, 82, 251, 165, 132, 133, 133, 160, 1, 162, 30, 32, 88, 251, - 56, 96, 169, 0, 133, 133, 160, 0, 132, 134, 24, 165, 133, 101, 134, 133, - 133, 133, 2, 133, 9, 202, 208, 242, 96, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 250, 0, 250, 0, 250, +static constexpr unsigned char kernelROM[] = { + 133, 2, 185, 50, 248, 133, 27, 185, 62, 248, 133, 28, 185, 74, 248, 133, + 27, 185, 86, 248, 133, 135, 185, 98, 248, 190, 110, 248, 132, 136, 164, 135, + 132, 28, 133, 27, 134, 28, 134, 27, 164, 136, 102, 137, 176, 210, 136, 16, + 207, 96, 0, 1, 1, 1, 0, 0, 48, 48, 50, 53, 56, 48, 249, 129, + 129, 128, 248, 0, 99, 102, 102, 102, 230, 99, 140, 252, 140, 136, 112, 0, + 192, 97, 99, 102, 102, 198, 198, 198, 248, 198, 248, 0, 193, 32, 48, 24, + 24, 25, 24, 24, 24, 24, 126, 0, 249, 97, 97, 97, 97, 249, 0, 0, + 0, 0, 0, 0, 248, 128, 128, 224, 128, 248, 255, 255, 255, 255, 255, 255, + 165, 12, 10, 173, 130, 2, 42, 41, 23, 133, 129, 133, 128, 133, 128, 133, + 128, 133, 128, 133, 128, 234, 96, 173, 128, 2, 74, 74, 74, 133, 129, 133, + 128, 133, 128, 133, 128, 133, 128, 133, 128, 133, 128, 234, 96, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 133, 25, 133, 128, + 134, 32, 134, 33, 169, 243, 133, 27, 169, 207, 133, 28, 169, 251, 133, 27, + 169, 239, 162, 191, 160, 66, 133, 28, 169, 54, 133, 6, 134, 27, 169, 238, + 133, 7, 132, 6, 132, 28, 169, 182, 133, 6, 169, 114, 133, 7, 133, 42, + 162, 0, 162, 0, 169, 0, 162, 128, 133, 25, 134, 32, 134, 33, 169, 231, + 133, 27, 169, 159, 133, 28, 169, 253, 133, 27, 169, 247, 162, 223, 160, 242, + 133, 28, 169, 248, 133, 6, 134, 27, 169, 172, 133, 7, 132, 6, 132, 28, + 169, 216, 133, 6, 169, 98, 133, 7, 169, 0, 162, 0, 162, 0, 162, 0, + 133, 42, 76, 76, 249, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 120, 216, 162, 255, 154, 169, 0, 149, 0, 202, 208, 251, 169, 128, 133, 130, + 169, 251, 133, 131, 169, 1, 133, 37, 133, 38, 169, 3, 133, 4, 133, 5, + 133, 2, 162, 4, 133, 128, 202, 208, 251, 133, 128, 133, 16, 133, 17, 169, + 208, 133, 32, 169, 224, 133, 33, 133, 2, 133, 42, 165, 132, 106, 106, 133, + 6, 133, 7, 169, 85, 133, 137, 32, 0, 251, 176, 239, 169, 0, 133, 9, + 141, 129, 2, 141, 131, 2, 169, 6, 133, 4, 169, 2, 133, 5, 169, 0, + 133, 2, 133, 128, 76, 128, 250, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 133, 25, 169, 0, 133, 27, 133, 28, 133, 27, 133, 28, 133, 128, 133, 128, + 133, 128, 169, 0, 133, 16, 234, 133, 17, 169, 208, 133, 32, 169, 192, 133, + 33, 169, 0, 133, 2, 133, 42, 133, 128, 133, 25, 160, 0, 162, 28, 32, + 212, 250, 169, 2, 133, 0, 162, 3, 32, 212, 250, 169, 0, 133, 0, 169, + 2, 133, 1, 162, 37, 32, 212, 250, 162, 0, 134, 1, 32, 128, 248, 169, + 0, 76, 76, 249, 177, 130, 133, 2, 133, 128, 133, 128, 133, 25, 165, 129, + 240, 5, 198, 129, 173, 128, 20, 200, 202, 208, 233, 96, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 162, 30, 32, 82, 251, 169, 2, 133, 0, 162, 3, 32, 82, 251, 169, 0, + 133, 0, 169, 2, 133, 1, 162, 37, 32, 82, 251, 169, 0, 133, 1, 198, + 132, 165, 132, 133, 133, 160, 255, 162, 30, 32, 88, 251, 162, 54, 32, 82, + 251, 160, 11, 32, 0, 248, 169, 0, 133, 27, 133, 28, 133, 27, 133, 28, + 162, 54, 32, 82, 251, 165, 132, 133, 133, 160, 1, 162, 30, 32, 88, 251, + 56, 96, 169, 0, 133, 133, 160, 0, 132, 134, 24, 165, 133, 101, 134, 133, + 133, 133, 2, 133, 9, 202, 208, 242, 96, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 250, 0, 250, 0, 250, }; // OSD labels - -const uint8_t brightLabelEven[] = -{ - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 225, 48, 12, 252, - 6, 140, 231, 96, 0, - 0, 113, 48, 12, 96, - 6, 140, 192, 96, 0, - 0, 225, 49, 15, 96, - 6, 152, 195, 96, 0, - 0, 49, 48, 12, 96, - 6, 140, 231, 96, 0, - 0, 225, 48, 12, 96, +static constexpr uInt8 brightLabelEven[] = { + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 225, 48, 12, 252, + 6, 140, 231, 96, 0, + 0, 113, 48, 12, 96, + 6, 140, 192, 96, 0, + 0, 225, 49, 15, 96, + 6, 152, 195, 96, 0, + 0, 49, 48, 12, 96, + 6, 140, 231, 96, 0, + 0, 225, 48, 12, 96, }; -const uint8_t brightLabelOdd[] = -{ - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 7, 252, 126, 99, 0, - 0, 113, 48, 12, 96, - 6, 140, 192, 96, 0, - 0, 97, 49, 12, 96, - 7, 248, 223, 224, 0, - 0, 113, 49, 12, 96, - 6, 156, 195, 96, 0, - 0, 113, 48, 12, 96, - 7, 142, 127, 96, 0, - 0, 0, 0, 0, 0 +static constexpr uInt8 brightLabelOdd[] = { + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 7, 252, 126, 99, 0, + 0, 113, 48, 12, 96, + 6, 140, 192, 96, 0, + 0, 97, 49, 12, 96, + 7, 248, 223, 224, 0, + 0, 113, 49, 12, 96, + 6, 156, 195, 96, 0, + 0, 113, 48, 12, 96, + 7, 142, 127, 96, 0, + 0, 0, 0, 0, 0 }; -const uint8_t volumeLabelEven[] = -{ - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 199, 192, 14, 254, - 113, 112, 99, 112, 0, - 0, 140, 192, 14, 192, - 51, 48, 99, 240, 0, - 0, 28, 192, 15, 254, - 31, 48, 99, 240, 0, - 0, 12, 192, 15, 192, - 30, 112, 119, 176, 0, - 0, 7, 252, 12, 254, +static constexpr uInt8 volumeLabelEven[] = { + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 199, 192, 14, 254, + 113, 112, 99, 112, 0, + 0, 140, 192, 14, 192, + 51, 48, 99, 240, 0, + 0, 28, 192, 15, 254, + 31, 48, 99, 240, 0, + 0, 12, 192, 15, 192, + 30, 112, 119, 176, 0, + 0, 7, 252, 12, 254, }; -const uint8_t volumeLabelOdd[] = -{ - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 97, 224, 99, 112, 0, - 0, 142, 192, 14, 192, - 51, 112, 99, 112, 0, - 0, 28, 192, 15, 192, - 59, 48, 99, 240, 0, - 0, 28, 192, 15, 192, - 30, 112, 99, 176, 0, - 0, 14, 192, 13, 192, - 14, 224, 62, 48, 0, - 0, 0, 0, 0, 0 +static constexpr uInt8 volumeLabelOdd[] = { + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 97, 224, 99, 112, 0, + 0, 142, 192, 14, 192, + 51, 112, 99, 112, 0, + 0, 28, 192, 15, 192, + 59, 48, 99, 240, 0, + 0, 28, 192, 15, 192, + 30, 112, 99, 176, 0, + 0, 14, 192, 13, 192, + 14, 224, 62, 48, 0, + 0, 0, 0, 0, 0 }; // Level bars // 8 rows * 5 columns = 40 - -const uint8_t levelBarsEvenData[] = -{ - /**/ - 0, 0, 0, 0, 0, - 3, 239, 191, 253, 247, - 247, 223, 126, 251, 224, - 2, 40, 161, 133, 20, - 20, 80, 66, 10, 32, - 3, 239, 191, 253, 247, - 247, 223, 126, 251, 224, - 0, 0, 0, 0, 0, - /**/ - 0, 0, 0, 0, 0, - 3, 239, 191, 253, 247, - 247, 223, 126, 251, 224, - 3, 40, 161, 133, 20, - 244, 80, 66, 10, 32, - 3, 239, 191, 253, 247, - 247, 223, 126, 251, 224, - 0, 0, 0, 0, 0, - /**/ - 0, 0, 0, 0, 0, - 3, 239, 191, 253, 247, - 247, 223, 126, 251, 224, - 3, 232, 161, 133, 20, - 247, 80, 66, 10, 32, - 3, 239, 191, 253, 247, - 247, 223, 126, 251, 224, - 0, 0, 0, 0, 0, - /**/ - 0, 0, 0, 0, 0, - 3, 239, 191, 253, 247, - 247, 223, 126, 251, 224, - 3, 239, 161, 133, 20, - 247, 208, 66, 10, 32, - 3, 239, 191, 253, 247, - 247, 223, 126, 251, 224, - 0, 0, 0, 0, 0, - /**/ - 0, 0, 0, 0, 0, - 3, 239, 191, 253, 247, - 247, 223, 126, 251, 224, - 3, 239, 161, 133, 20, - 247, 223, 66, 10, 32, - 3, 239, 191, 253, 247, - 247, 223, 126, 251, 224, - 0, 0, 0, 0, 0, - /**/ - 0, 0, 0, 0, 0, - 3, 239, 191, 253, 247, - 247, 223, 126, 251, 224, - 3, 239, 191, 133, 20, - 247, 223, 66, 10, 32, - 3, 239, 191, 253, 247, - 247, 223, 126, 251, 224, - 0, 0, 0, 0, 0, - /**/ - 0, 0, 0, 0, 0, - 3, 239, 191, 253, 247, - 247, 223, 126, 251, 224, - 3, 239, 191, 133, 20, - 247, 223, 126, 10, 32, - 3, 239, 191, 253, 247, - 247, 223, 126, 251, 224, - 0, 0, 0, 0, 0, - /**/ - 0, 0, 0, 0, 0, - 3, 239, 191, 253, 247, - 247, 223, 126, 251, 224, - 3, 239, 191, 253, 20, - 247, 223, 126, 10, 32, - 3, 239, 191, 253, 247, - 247, 223, 126, 251, 224, - 0, 0, 0, 0, 0, - /**/ - 0, 0, 0, 0, 0, - 3, 239, 191, 253, 247, - 247, 223, 126, 251, 224, - 3, 239, 191, 253, 20, - 247, 223, 126, 250, 32, - 3, 239, 191, 253, 247, - 247, 223, 126, 251, 224, - 0, 0, 0, 0, 0, - /**/ - 0, 0, 0, 0, 0, - 3, 239, 191, 253, 247, - 247, 223, 126, 251, 224, - 3, 239, 191, 253, 244, - 247, 223, 126, 251, 32, - 3, 239, 191, 253, 247, - 247, 223, 126, 251, 224, - 0, 0, 0, 0, 0, - /**/ - 0, 0, 0, 0, 0, - 3, 239, 191, 253, 247, - 247, 223, 126, 251, 224, - 3, 239, 191, 253, 247, - 247, 223, 126, 251, 224, - 3, 239, 191, 253, 247, - 247, 223, 126, 251, 224, - 0, 0, 0, 0, 0, - +static constexpr uInt8 levelBarsEvenData[] = { + /**/ + 0, 0, 0, 0, 0, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 2, 40, 161, 133, 20, + 20, 80, 66, 10, 32, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 0, 0, 0, 0, 0, + /**/ + 0, 0, 0, 0, 0, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 3, 40, 161, 133, 20, + 244, 80, 66, 10, 32, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 0, 0, 0, 0, 0, + /**/ + 0, 0, 0, 0, 0, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 3, 232, 161, 133, 20, + 247, 80, 66, 10, 32, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 0, 0, 0, 0, 0, + /**/ + 0, 0, 0, 0, 0, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 3, 239, 161, 133, 20, + 247, 208, 66, 10, 32, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 0, 0, 0, 0, 0, + /**/ + 0, 0, 0, 0, 0, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 3, 239, 161, 133, 20, + 247, 223, 66, 10, 32, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 0, 0, 0, 0, 0, + /**/ + 0, 0, 0, 0, 0, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 3, 239, 191, 133, 20, + 247, 223, 66, 10, 32, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 0, 0, 0, 0, 0, + /**/ + 0, 0, 0, 0, 0, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 3, 239, 191, 133, 20, + 247, 223, 126, 10, 32, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 0, 0, 0, 0, 0, + /**/ + 0, 0, 0, 0, 0, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 20, + 247, 223, 126, 10, 32, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 0, 0, 0, 0, 0, + /**/ + 0, 0, 0, 0, 0, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 20, + 247, 223, 126, 250, 32, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 0, 0, 0, 0, 0, + /**/ + 0, 0, 0, 0, 0, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 244, + 247, 223, 126, 251, 32, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 0, 0, 0, 0, 0, + /**/ + 0, 0, 0, 0, 0, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 0, 0, 0, 0, 0, }; -const uint8_t levelBarsOddData[] = -{ - /**/ - 247, 223, 126, 251, 224, - 3, 239, 191, 253, 247, - 20, 80, 66, 10, 32, - 2, 40, 161, 133, 20, - 247, 223, 126, 251, 224, - 3, 239, 191, 253, 247, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - /**/ - 247, 223, 126, 251, 224, - 3, 239, 191, 253, 247, - 244, 80, 66, 10, 32, - 3, 40, 161, 133, 20, - 247, 223, 126, 251, 224, - 3, 239, 191, 253, 247, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - /**/ - 247, 223, 126, 251, 224, - 3, 239, 191, 253, 247, - 247, 80, 66, 10, 32, - 3, 232, 161, 133, 20, - 247, 223, 126, 251, 224, - 3, 239, 191, 253, 247, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - /**/ - 247, 223, 126, 251, 224, - 3, 239, 191, 253, 247, - 247, 208, 66, 10, 32, - 3, 239, 161, 133, 20, - 247, 223, 126, 251, 224, - 3, 239, 191, 253, 247, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - /**/ - 247, 223, 126, 251, 224, - 3, 239, 191, 253, 247, - 247, 223, 66, 10, 32, - 3, 239, 161, 133, 20, - 247, 223, 126, 251, 224, - 3, 239, 191, 253, 247, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - /**/ - 247, 223, 126, 251, 224, - 3, 239, 191, 253, 247, - 247, 223, 66, 10, 32, - 3, 239, 191, 133, 20, - 247, 223, 126, 251, 224, - 3, 239, 191, 253, 247, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - /**/ - 247, 223, 126, 251, 224, - 3, 239, 191, 253, 247, - 247, 223, 126, 10, 32, - 3, 239, 191, 133, 20, - 247, 223, 126, 251, 224, - 3, 239, 191, 253, 247, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - /**/ - 247, 223, 126, 251, 224, - 3, 239, 191, 253, 247, - 247, 223, 126, 10, 32, - 3, 239, 191, 253, 20, - 247, 223, 126, 251, 224, - 3, 239, 191, 253, 247, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - /**/ - 247, 223, 126, 251, 224, - 3, 239, 191, 253, 247, - 247, 223, 126, 250, 32, - 3, 239, 191, 253, 20, - 247, 223, 126, 251, 224, - 3, 239, 191, 253, 247, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - /**/ - 247, 223, 126, 251, 224, - 3, 239, 191, 253, 247, - 247, 223, 126, 251, 32, - 3, 239, 191, 253, 244, - 247, 223, 126, 251, 224, - 3, 239, 191, 253, 247, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - /**/ - 247, 223, 126, 251, 224, - 3, 239, 191, 253, 247, - 247, 223, 126, 251, 224, - 3, 239, 191, 253, 247, - 247, 223, 126, 251, 224, - 3, 239, 191, 253, 247, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, +static constexpr uInt8 levelBarsOddData[] = { + /**/ + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 20, 80, 66, 10, 32, + 2, 40, 161, 133, 20, + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + /**/ + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 244, 80, 66, 10, 32, + 3, 40, 161, 133, 20, + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + /**/ + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 247, 80, 66, 10, 32, + 3, 232, 161, 133, 20, + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + /**/ + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 247, 208, 66, 10, 32, + 3, 239, 161, 133, 20, + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + /**/ + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 247, 223, 66, 10, 32, + 3, 239, 161, 133, 20, + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + /**/ + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 247, 223, 66, 10, 32, + 3, 239, 191, 133, 20, + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + /**/ + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 247, 223, 126, 10, 32, + 3, 239, 191, 133, 20, + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + /**/ + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 247, 223, 126, 10, 32, + 3, 239, 191, 253, 20, + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + /**/ + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 247, 223, 126, 250, 32, + 3, 239, 191, 253, 20, + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + /**/ + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 32, + 3, 239, 191, 253, 244, + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + /**/ + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 247, 223, 126, 251, 224, + 3, 239, 191, 253, 247, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, }; //////////////////////////////////////////////////////////////////////////////// - - class MovieCart { + public: -public: + MovieCart(); + ~MovieCart(); - MovieCart(); - ~MovieCart(); + bool init(const std::string& path); + bool process(uint16_t address); - bool init(const std::string& path); - bool process(uint16_t address); + uInt8 + readROM(uint16_t address) + { + return myROM[address & 1023]; + } - uint8_t - readROM(uint16_t address) - { - return myROM[address & 1023]; - } - - void - writeROM(uint16_t address, uint8_t data) - { - myROM[address & 1023] = data; - } + void + writeROM(uint16_t address, uInt8 data) + { + myROM[address & 1023] = data; + } private: - enum Mode - { - Volume, - Bright, - Time, - Last = Time - }; + enum Mode + { + Volume, + Bright, + Time, + Last = Time + }; - enum TitleState - { - Display, - Exiting, - Stream - }; + enum TitleState + { + Display, + Exiting, + Stream + }; - void stopTitleScreen(); + void stopTitleScreen(); - void writeColor(uint16_t address); - void writeAudioData(uint16_t address, uint8_t val); - void writeAudio(uint16_t address); - void writeGraph(uint16_t address); + void writeColor(uint16_t address); + void writeAudioData(uint16_t address, uInt8 val); + void writeAudio(uint16_t address); + void writeGraph(uint16_t address); - void runStateMachine(); + void runStateMachine(); - void fill_addr_right_line(); - void fill_addr_left_line(bool again); - void fill_addr_end_lines(); - void fill_addr_blank_lines(); + void fill_addr_right_line(); + void fill_addr_left_line(bool again); + void fill_addr_end_lines(); + void fill_addr_blank_lines(); - void updateTransport(); + void updateTransport(); - StreamReader myStream; + StreamReader myStream; - // data + // data - uint8_t myROM[1024]; + uInt8 myROM[1024]; - // title screen state - int myTitleCycles; - uint8_t myTitleState; - - - // address info - bool myA7; - bool myA10; - uint8_t myA10_Count; - - // state machine info - - uint8_t myState; - bool myPlaying; - bool myOdd; - bool myBufferIndex; + // title screen state + int myTitleCycles; + uInt8 myTitleState; - uint8_t myLines; - int32_t myFrameNumber; // signed + // address info + bool myA7; + bool myA10; + uInt8 myA10_Count; - uint8_t myMode; - uint8_t myBright; - uint8_t myForceColor; + // state machine info - // expressed in frames - uint8_t myDrawLevelBars; - uint8_t myDrawTimeCode; + uInt8 myState; + bool myPlaying; + bool myOdd; + bool myBufferIndex; - MovieInputs myInputs; - MovieInputs myLastInputs; - int8_t mySpeed; // signed - uint8_t myJoyRepeat; - uint8_t myDirectionValue; - uint8_t myButtonsValue; + uInt8 myLines; + int32_t myFrameNumber; // signed - uint8_t myVolume; - const uint8_t* myVolumeScale; - uint8_t myFirstAudioVal; + uInt8 myMode; + uInt8 myBright; + uInt8 myForceColor; + + // expressed in frames + uInt8 myDrawLevelBars; + uInt8 myDrawTimeCode; + + MovieInputs myInputs; + MovieInputs myLastInputs; + + int8_t mySpeed; // signed + uInt8 myJoyRepeat; + uInt8 myDirectionValue; + uInt8 myButtonsValue; + + uInt8 myVolume; + const uInt8* myVolumeScale; + uInt8 myFirstAudioVal; }; @@ -823,600 +727,605 @@ MovieCart::~MovieCart() bool MovieCart::init(const std::string& path) { - memcpy(myROM, kernelROM, 1024); + memcpy(myROM, kernelROM, 1024); - myTitleCycles = 0; - myTitleState = TitleState::Display; + myTitleCycles = 0; + myTitleState = TitleState::Display; - myA7 = false; - myA10 = false; - myA10_Count = 0; + myA7 = false; + myA10 = false; + myA10_Count = 0; - myState = 3; - myPlaying = true; - myOdd = true; - myBufferIndex = false; - myFrameNumber = 1; + myState = 3; + myPlaying = true; + myOdd = true; + myBufferIndex = false; + myFrameNumber = 1; - myInputs.init(); - myLastInputs.init(); - mySpeed = 1; - myJoyRepeat = 0; - myDirectionValue = 0; - myButtonsValue = 0; + myInputs.init(); + myLastInputs.init(); + mySpeed = 1; + myJoyRepeat = 0; + myDirectionValue = 0; + myButtonsValue = 0; - myLines = 0; - myForceColor = 0; - myDrawLevelBars = 0; - myDrawTimeCode = 0; - myFirstAudioVal = 0; + myLines = 0; + myForceColor = 0; + myDrawLevelBars = 0; + myDrawTimeCode = 0; + myFirstAudioVal = 0; - myMode = Mode::Volume; - myVolume = DEFAULT_LEVEL; + myMode = Mode::Volume; + myVolume = DEFAULT_LEVEL; myVolumeScale = scales[DEFAULT_LEVEL]; - myBright = DEFAULT_LEVEL; + myBright = DEFAULT_LEVEL; - if (!myStream.open(path)) - return false; - - myStream.swapField(true); + if (!myStream.open(path)) + return false; - return true; + myStream.swapField(true); + + return true; } void MovieCart::stopTitleScreen() { - writeROM(addr_title_loop + 0, 0x18); // clear carry, one bit difference from 0x38 sec + writeROM(addr_title_loop + 0, 0x18); // clear carry, one bit difference from 0x38 sec } void MovieCart::writeColor(uint16_t address) { - uint8_t v = myStream.readColor(); - v = (v & 0xf0) | shiftBright[(v & 0x0f) + myBright]; + uInt8 v = myStream.readColor(); + v = (v & 0xf0) | shiftBright[(v & 0x0f) + myBright]; - if (myForceColor) - v = myForceColor; - if (myInputs.bw) - v &= 0x0f; + if (myForceColor) + v = myForceColor; + if (myInputs.bw) + v &= 0x0f; - writeROM(address, v); + writeROM(address, v); } void -MovieCart::writeAudioData(uint16_t address, uint8_t val) +MovieCart::writeAudioData(uint16_t address, uInt8 val) { - uint8_t v; - v = myVolumeScale[val]; - writeROM(address, v); + uInt8 v; + v = myVolumeScale[val]; + writeROM(address, v); } void MovieCart::writeAudio(uint16_t address) { - uint8_t v = myStream.readAudio(); - writeAudioData(address, v); + uInt8 v = myStream.readAudio(); + writeAudioData(address, v); } void MovieCart::writeGraph(uint16_t address) { - uint8_t v = myStream.readGraph(); - writeROM(address, v); + uInt8 v = myStream.readGraph(); + writeROM(address, v); } void MovieCart::updateTransport() { - myStream.overrideGraph(nullptr); + myStream.overrideGraph(nullptr); + - // have to cut rate in half, to remove glitches...todo.. { if (myBufferIndex == true) { - uint8_t temp = ~(myA10_Count & 0x1e) & 0x1e; + uInt8 temp = ~(myA10_Count & 0x1e) & 0x1e; if (temp == myDirectionValue) - myInputs.updateDirection(temp); + myInputs.updateDirection(temp); - myDirectionValue = temp; + myDirectionValue = temp; } else { - uint8_t temp = ~(myA10_Count & 0x17) & 0x17; + uInt8 temp = ~(myA10_Count & 0x17) & 0x17; if (temp == myButtonsValue) - myInputs.updateTransport(temp); + myInputs.updateTransport(temp); myButtonsValue = temp; } - myA10_Count = 0; + myA10_Count = 0; } - if (myInputs.reset) - { - myFrameNumber = 1; - myPlaying = true; - myDrawTimeCode = OSD_FRAMES; + if (myInputs.reset) + { + myFrameNumber = 1; + myPlaying = true; + myDrawTimeCode = OSD_FRAMES; - goto update_stream; - } + // goto update_stream; + myLastInputs = myInputs; + return; + } - uint8_t lastMainMode = myMode; + uInt8 lastMainMode = myMode; - if (myInputs.up && !myLastInputs.up) - { - if (myMode == 0) - myMode = Mode::Last; - else - myMode--; - } - else if (myInputs.down && !myLastInputs.down) - { - if (myMode == Mode::Last) - myMode = 0; - else - myMode++; - } + if (myInputs.up && !myLastInputs.up) + { + if (myMode == 0) + myMode = Mode::Last; + else + myMode--; + } + else if (myInputs.down && !myLastInputs.down) + { + if (myMode == Mode::Last) + myMode = 0; + else + myMode++; + } - if (myInputs.left || myInputs.right) - { - myJoyRepeat++; - } - else - { - myJoyRepeat = 0; - mySpeed = 1; - } + if (myInputs.left || myInputs.right) + { + myJoyRepeat++; + } + else + { + myJoyRepeat = 0; + mySpeed = 1; + } - if (myJoyRepeat & 16) - { - myJoyRepeat = 0; + if (myJoyRepeat & 16) + { + myJoyRepeat = 0; - if (myInputs.left || myInputs.right) - { - if (myMode == Mode::Time) - { - myDrawTimeCode = OSD_FRAMES; - mySpeed += 4; - if (mySpeed < 0) - mySpeed -= 4; - } - else if (myMode == Mode::Volume) - { - myDrawLevelBars = OSD_FRAMES; - if (myInputs.left) - { - if (myVolume) - myVolume--; - } - else - { - myVolume++; - if (myVolume >= MAX_LEVEL) - myVolume--; - } - } - else if (myMode == Mode::Bright) - { - myDrawLevelBars = OSD_FRAMES; - if (myInputs.left) - { - if (myBright) - myBright--; - } - else - { - myBright++; - if (myBright >= MAX_LEVEL) - myBright--; - } - } - } - } + if (myInputs.left || myInputs.right) + { + if (myMode == Mode::Time) + { + myDrawTimeCode = OSD_FRAMES; + mySpeed += 4; + if (mySpeed < 0) + mySpeed -= 4; + } + else if (myMode == Mode::Volume) + { + myDrawLevelBars = OSD_FRAMES; + if (myInputs.left) + { + if (myVolume) + myVolume--; + } + else + { + myVolume++; + if (myVolume >= MAX_LEVEL) + myVolume--; + } + } + else if (myMode == Mode::Bright) + { + myDrawLevelBars = OSD_FRAMES; + if (myInputs.left) + { + if (myBright) + myBright--; + } + else + { + myBright++; + if (myBright >= MAX_LEVEL) + myBright--; + } + } + } + } - if (myInputs.select && !myLastInputs.select) - { - myDrawTimeCode = OSD_FRAMES; - myFrameNumber -= 60 * BACK_SECONDS + 1; - goto update_stream; - } + if (myInputs.select && !myLastInputs.select) + { + myDrawTimeCode = OSD_FRAMES; + myFrameNumber -= 60 * BACK_SECONDS + 1; + //goto update_stream; + myLastInputs = myInputs; + return; + } - if (myInputs.fire && !myLastInputs.fire) - myPlaying = !myPlaying; + if (myInputs.fire && !myLastInputs.fire) + myPlaying = !myPlaying; - switch (myMode) - { - case Mode::Time: - if (lastMainMode != myMode) - myDrawTimeCode = OSD_FRAMES; - break; + switch (myMode) + { + case Mode::Time: + if (lastMainMode != myMode) + myDrawTimeCode = OSD_FRAMES; + break; - case Mode::Bright: - case Mode::Volume: - default: - if (lastMainMode != myMode) - myDrawLevelBars = OSD_FRAMES; - break; - } + case Mode::Bright: + case Mode::Volume: + default: + if (lastMainMode != myMode) + myDrawLevelBars = OSD_FRAMES; + break; + } - // just draw one - if (myDrawLevelBars > myDrawTimeCode) - myDrawTimeCode = 0; - else - myDrawLevelBars = 0; + // just draw one + if (myDrawLevelBars > myDrawTimeCode) + myDrawTimeCode = 0; + else + myDrawLevelBars = 0; - if (myPlaying) - myVolumeScale = scales[myVolume]; - else - myVolumeScale = scales[0]; + if (myPlaying) + myVolumeScale = scales[myVolume]; + else + myVolumeScale = scales[0]; - // update frame + // update frame - int8_t step = 1; + int8_t step = 1; - if (!myPlaying) // step while paused - { - if (myMode == Mode::Time) - { - if (myInputs.right && !myLastInputs.right) - step = 3; - else if (myInputs.left && !myLastInputs.left) - step = -3; - else - step = (myFrameNumber & 1) ? -1 : 1; - } - else - { - step = (myFrameNumber & 1) ? -1 : 1; - } - } - else - { - if (myMode == Mode::Time) - { - if (myInputs.right) - step = mySpeed; - else if (myInputs.left) - step = -mySpeed; - } - else - { - step = 1; - } - } + if (!myPlaying) // step while paused + { + if (myMode == Mode::Time) + { + if (myInputs.right && !myLastInputs.right) + step = 3; + else if (myInputs.left && !myLastInputs.left) + step = -3; + else + step = (myFrameNumber & 1) ? -1 : 1; + } + else + { + step = (myFrameNumber & 1) ? -1 : 1; + } + } + else + { + if (myMode == Mode::Time) + { + if (myInputs.right) + step = mySpeed; + else if (myInputs.left) + step = -mySpeed; + } + else + { + step = 1; + } + } - myFrameNumber += step; - if (myFrameNumber < 1) - { - myFrameNumber = 1; - mySpeed = 1; - } - -update_stream: - - myLastInputs = myInputs; + myFrameNumber += step; + if (myFrameNumber < 1) + { + myFrameNumber = 1; + mySpeed = 1; + } + myLastInputs = myInputs; } void MovieCart::fill_addr_right_line() { - writeGraph(addr_right_line + 9); // #GDATA0 - writeGraph(addr_right_line + 13); // #GDATA1 - writeGraph(addr_right_line + 17); // #GDATA2 - writeGraph(addr_right_line + 21); // #GDATA3 - writeGraph(addr_right_line + 23); // #GDATA4 + writeGraph(addr_right_line + 9); // #GDATA0 + writeGraph(addr_right_line + 13); // #GDATA1 + writeGraph(addr_right_line + 17); // #GDATA2 + writeGraph(addr_right_line + 21); // #GDATA3 + writeGraph(addr_right_line + 23); // #GDATA4 - writeColor(addr_right_line + 25); // #GCOL0 - writeColor(addr_right_line + 29); // #GCOL1 - writeColor(addr_right_line + 35); // #GCOL2 - writeColor(addr_right_line + 43); // #GCOL3 - writeColor(addr_right_line + 47); // #GCOL4 + writeColor(addr_right_line + 25); // #GCOL0 + writeColor(addr_right_line + 29); // #GCOL1 + writeColor(addr_right_line + 35); // #GCOL2 + writeColor(addr_right_line + 43); // #GCOL3 + writeColor(addr_right_line + 47); // #GCOL4 } void MovieCart::fill_addr_left_line(bool again) { - writeAudio(addr_left_line + 5); // #AUD_DATA + writeAudio(addr_left_line + 5); // #AUD_DATA - writeGraph(addr_left_line + 15); // #GDATA5 - writeGraph(addr_left_line + 19); // #GDATA6 - writeGraph(addr_left_line + 23); // #GDATA7 - writeGraph(addr_left_line + 27); // #GDATA8 - writeGraph(addr_left_line + 29); // #GDATA9 + writeGraph(addr_left_line + 15); // #GDATA5 + writeGraph(addr_left_line + 19); // #GDATA6 + writeGraph(addr_left_line + 23); // #GDATA7 + writeGraph(addr_left_line + 27); // #GDATA8 + writeGraph(addr_left_line + 29); // #GDATA9 - writeColor(addr_left_line + 31); // #GCOL5 - writeColor(addr_left_line + 35); // #GCOL6 - writeColor(addr_left_line + 41); // #GCOL7 - writeColor(addr_left_line + 49); // #GCOL8 - writeColor(addr_left_line + 53); // #GCOL9 + writeColor(addr_left_line + 31); // #GCOL5 + writeColor(addr_left_line + 35); // #GCOL6 + writeColor(addr_left_line + 41); // #GCOL7 + writeColor(addr_left_line + 49); // #GCOL8 + writeColor(addr_left_line + 53); // #GCOL9 - writeAudio(addr_left_line + 57); // #AUD_DATA + writeAudio(addr_left_line + 57); // #AUD_DATA - // addr_pick_line_end = 0x0ee; - // jmp right_line - // jmp end_lines - if (again) - { - writeROM(addr_pick_continue + 1, LO_JUMP_BYTE(addr_right_line)); - writeROM(addr_pick_continue + 2, HI_JUMP_BYTE(addr_right_line)); - } - else - { - writeROM(addr_pick_continue + 1, LO_JUMP_BYTE(addr_end_lines)); - writeROM(addr_pick_continue + 2, HI_JUMP_BYTE(addr_end_lines)); - } + // addr_pick_line_end = 0x0ee; + // jmp right_line + // jmp end_lines + if (again) + { + writeROM(addr_pick_continue + 1, LO_JUMP_BYTE(addr_right_line)); + writeROM(addr_pick_continue + 2, HI_JUMP_BYTE(addr_right_line)); + } + else + { + writeROM(addr_pick_continue + 1, LO_JUMP_BYTE(addr_end_lines)); + writeROM(addr_pick_continue + 2, HI_JUMP_BYTE(addr_end_lines)); + } } void MovieCart::fill_addr_end_lines() { - writeAudio(addr_end_lines_audio + 1); - myFirstAudioVal = myStream.peekAudio(); + writeAudio(addr_end_lines_audio + 1); + myFirstAudioVal = myStream.peekAudio(); - // normally overscan=28, vblank=37 - // todo: clicky noise.. - if (myOdd) - { - writeROM(addr_set_overscan_size + 1, 28); - writeROM(addr_set_vblank_size + 1, 36); - } - else - { - writeROM(addr_set_overscan_size + 1, 29); - writeROM(addr_set_vblank_size + 1, 37); - } + // normally overscan=28, vblank=37 + // todo: clicky noise.. + if (myOdd) + { + writeROM(addr_set_overscan_size + 1, 28); + writeROM(addr_set_vblank_size + 1, 36); + } + else + { + writeROM(addr_set_overscan_size + 1, 29); + writeROM(addr_set_vblank_size + 1, 37); + } - if (myBufferIndex == false) - { - writeROM(addr_pick_transport + 1, LO_JUMP_BYTE(addr_transport_direction)); - writeROM(addr_pick_transport + 2, HI_JUMP_BYTE(addr_transport_direction)); - } - else - { - writeROM(addr_pick_transport + 1, LO_JUMP_BYTE(addr_transport_buttons)); - writeROM(addr_pick_transport + 2, HI_JUMP_BYTE(addr_transport_buttons)); - } + if (myBufferIndex == false) + { + writeROM(addr_pick_transport + 1, LO_JUMP_BYTE(addr_transport_direction)); + writeROM(addr_pick_transport + 2, HI_JUMP_BYTE(addr_transport_direction)); + } + else + { + writeROM(addr_pick_transport + 1, LO_JUMP_BYTE(addr_transport_buttons)); + writeROM(addr_pick_transport + 2, HI_JUMP_BYTE(addr_transport_buttons)); + } } void MovieCart::fill_addr_blank_lines() { - uint8_t i; - uint8_t v; + uInt8 i; + uInt8 v; - // version number - myStream.readVersion(); - myStream.readVersion(); - myStream.readVersion(); - myStream.readVersion(); + // version number + myStream.readVersion(); + myStream.readVersion(); + myStream.readVersion(); + myStream.readVersion(); - // frame number - myStream.readFrame(); - myStream.readFrame(); - v = myStream.readFrame(); - - // make sure we're in sync with frame data - myOdd = (v & 1); + // frame number + myStream.readFrame(); + myStream.readFrame(); + v = myStream.readFrame(); - // 28 overscan - // 3 vsync - // 37 vblank - - if (myOdd) - { - writeAudioData(addr_audio_bank + 0, myFirstAudioVal); - for (i = 1; i < (BLANK_LINE_SIZE + 1); i++) - writeAudio(addr_audio_bank + i); - } - else - { - for (i = 0; i < (BLANK_LINE_SIZE -1); i++) - writeAudio(addr_audio_bank + i); - } + // make sure we're in sync with frame data + myOdd = (v & 1); - writeAudio(addr_last_audio + 1); + // 28 overscan + // 3 vsync + // 37 vblank + + if (myOdd) + { + writeAudioData(addr_audio_bank + 0, myFirstAudioVal); + for (i = 1; i < (BLANK_LINE_SIZE + 1); i++) + writeAudio(addr_audio_bank + i); + } + else + { + for (i = 0; i < (BLANK_LINE_SIZE -1); i++) + writeAudio(addr_audio_bank + i); + } + + writeAudio(addr_last_audio + 1); } void MovieCart::runStateMachine() -{ - switch(myState) - { - case 1: - if (myA7) - { - if (myLines == (TIMECODE_HEIGHT-1)) - { - if (myDrawTimeCode) - { - myDrawTimeCode--; - myForceColor = COLOR_BLUE; - myStream.startTimeCode(); - } - } +{ + switch(myState) + { + case 1: + if (myA7) + { + if (myLines == (TIMECODE_HEIGHT-1)) + { + if (myDrawTimeCode) + { + myDrawTimeCode--; + myForceColor = COLOR_BLUE; + myStream.startTimeCode(); + } + } - // label = 12, bars = 7 - if (myLines == 21) - { - if (myDrawLevelBars) - { - myDrawLevelBars--; - myForceColor = COLOR_BLUE; + // label = 12, bars = 7 + if (myLines == 21) + { + if (myDrawLevelBars) + { + myDrawLevelBars--; + myForceColor = COLOR_BLUE; - switch (myMode) - { - case Mode::Time: - myStream.overrideGraph(nullptr); - break; + switch (myMode) + { + case Mode::Time: + myStream.overrideGraph(nullptr); + break; - case Mode::Bright: - if (myOdd) - myStream.overrideGraph(brightLabelOdd); - else - myStream.overrideGraph(brightLabelEven); - break; + case Mode::Bright: + if (myOdd) + myStream.overrideGraph(brightLabelOdd); + else + myStream.overrideGraph(brightLabelEven); + break; - case Mode::Volume: - default: - if (myOdd) - myStream.overrideGraph(volumeLabelOdd); - else - myStream.overrideGraph(volumeLabelEven); - break; - } - } - } + case Mode::Volume: + default: + if (myOdd) + myStream.overrideGraph(volumeLabelOdd); + else + myStream.overrideGraph(volumeLabelEven); + break; + } + } + } - if (myLines == 7) - { - if (myDrawLevelBars) - { - uint8_t levelValue; + if (myLines == 7) + { + if (myDrawLevelBars) + { + uInt8 levelValue; - switch (myMode) - { - case Mode::Time: - levelValue = 0; - break; + switch (myMode) + { + case Mode::Time: + levelValue = 0; + break; - case Mode::Bright: - levelValue = myBright; - break; + case Mode::Bright: + levelValue = myBright; + break; - case Mode::Volume: - default: - levelValue = myVolume; - break; - } + case Mode::Volume: + default: + levelValue = myVolume; + break; + } - if (myOdd) - myStream.overrideGraph(&levelBarsOddData[levelValue * 40]); - else - myStream.overrideGraph(&levelBarsEvenData[levelValue * 40]); - } - } + if (myOdd) + myStream.overrideGraph(&levelBarsOddData[levelValue * 40]); + else + myStream.overrideGraph(&levelBarsEvenData[levelValue * 40]); + } + } - fill_addr_right_line(); + fill_addr_right_line(); - myLines -= 1; - myState = 2; - } - break; + myLines -= 1; + myState = 2; + } + break; - case 2: - if (!myA7) - { - if (myLines >= 1) - { - fill_addr_left_line(1); + case 2: + if (!myA7) + { + if (myLines >= 1) + { + fill_addr_left_line(1); - myLines -= 1; - myState = 1; - } - else - { - fill_addr_left_line(0); - fill_addr_end_lines(); + myLines -= 1; + myState = 1; + } + else + { + fill_addr_left_line(0); + fill_addr_end_lines(); - myStream.swapField(myBufferIndex); - myBufferIndex = !myBufferIndex; - updateTransport(); + myStream.swapField(myBufferIndex); + myBufferIndex = !myBufferIndex; + updateTransport(); - fill_addr_blank_lines(); + fill_addr_blank_lines(); - myState = 3; - } - } - break; + myState = 3; + } + } + break; - case 3: - if (myA7) - { - // hit end? rewind just before end - while (myFrameNumber >= 2 && !myStream.readField(myFrameNumber, myBufferIndex)) - { - myFrameNumber -= 2; - myJoyRepeat = 0; - } + case 3: + if (myA7) + { + // hit end? rewind just before end + while (myFrameNumber >= 2 && !myStream.readField(myFrameNumber, myBufferIndex)) + { + myFrameNumber -= 2; + myJoyRepeat = 0; + } - myForceColor = 0; - myLines = 191; - myState = 1; - } - break; + myForceColor = 0; + myLines = 191; + myState = 1; + } + break; - default: - break; - } + default: + break; + } } bool MovieCart::process(uint16_t address) { - bool a12 = (address & (1 << 12)) ? 1:0; - bool a11 = (address & (1 << 11)) ? 1:0; + bool a12 = (address & (1 << 12)) ? 1:0; + bool a11 = (address & (1 << 11)) ? 1:0; - // count a10 pulses - bool a10i = (address & (1 << 10)); - if (a10i && !myA10) - myA10_Count++; - myA10 = a10i; + // count a10 pulses + bool a10i = (address & (1 << 10)); + if (a10i && !myA10) + myA10_Count++; + myA10 = a10i; - // latch a7 state - if (a11) // a12 - myA7 = (address & (1 << 7)); // each 128 + // latch a7 state + if (a11) // a12 + myA7 = (address & (1 << 7)); // each 128 - switch(myTitleState) - { - case TitleState::Display: - myTitleCycles++; - if (myTitleCycles == TITLE_CYCLES) - { - stopTitleScreen(); - myTitleState = TitleState::Exiting; - myTitleCycles = 0; - } - break; + switch(myTitleState) + { + case TitleState::Display: + myTitleCycles++; + if (myTitleCycles == TITLE_CYCLES) + { + stopTitleScreen(); + myTitleState = TitleState::Exiting; + myTitleCycles = 0; + } + break; - case TitleState::Exiting: - if (myA7) - myTitleState = TitleState::Stream; - break; + case TitleState::Exiting: + if (myA7) + myTitleState = TitleState::Stream; + break; - case TitleState::Stream: - runStateMachine(); - break; - } + case TitleState::Stream: + runStateMachine(); + break; + } - return a12; + return a12; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CartridgeMVC::CartridgeMVC(const string& path, size_t size, - const string& md5, const Settings& settings, - size_t bsSize) - : Cartridge(settings, md5) + const string& md5, const Settings& settings, + size_t bsSize) + : Cartridge(settings, md5), + mySize{bsSize} { myPath = path; myMovie = make_unique(); // not used - mySize = 1024; myImage = make_unique(mySize); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +CartridgeMVC::~CartridgeMVC() +{ +} // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CartridgeMVC::install(System& system) @@ -1433,11 +1342,10 @@ void CartridgeMVC::install(System& system) mySystem->setPageAccess(addr, access); } - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CartridgeMVC::reset() { - myMovie->init(myPath); + myMovie->init(myPath); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1465,6 +1373,5 @@ uInt8 CartridgeMVC::peek(uInt16 address) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool CartridgeMVC::poke(uInt16 address, uInt8 value) { - return myMovie->process(address); + return myMovie->process(address); } - diff --git a/src/emucore/CartMVC.hxx b/src/emucore/CartMVC.hxx old mode 100755 new mode 100644 index 2a4cf246f..3bac2e239 --- a/src/emucore/CartMVC.hxx +++ b/src/emucore/CartMVC.hxx @@ -33,26 +33,26 @@ class MovieCart; @author Rob Bairos */ - -#define MVC_FIELD_SIZE 2560 // round field to nearest 512 byte boundary -#define MVC_FIELD_PAD_SIZE 4096 // round to nearest 4K - class CartridgeMVC : public Cartridge { + public: + static constexpr uInt32 + MVC_FIELD_SIZE = 2560, // round field to nearest 512 byte boundary + MVC_FIELD_PAD_SIZE = 4096; // round to nearest 4K public: /** Create a new cartridge using the specified image - @param image Pointer to the ROM image + @param path Path to the ROM image file @param size The size of the ROM image (<= 2048 bytes) @param md5 The md5sum of the ROM image @param settings A reference to the various settings (read-only) @param bsSize The size specified by the bankswitching scheme */ CartridgeMVC(const string& path, size_t size, const string& md5, - const Settings& settings, size_t bsSize = 2_KB); - ~CartridgeMVC() override = default; + const Settings& settings, size_t bsSize = 1_KB); + ~CartridgeMVC() override; /** Reset device to its power-on state @@ -73,7 +73,7 @@ class CartridgeMVC : public Cartridge @param size Set to the size of the internal ROM image data @return A reference to the internal ROM image data */ - virtual const ByteBuffer& getImage(size_t& size) const; + const ByteBuffer& getImage(size_t& size) const override; /** Patch the cartridge ROM. @@ -82,7 +82,7 @@ class CartridgeMVC : public Cartridge @param value The value to place into the address @return Success or failure of the patch operation */ - virtual bool patch(uInt16 address, uInt8 value); + bool patch(uInt16 address, uInt8 value) override; /** Get the byte at the specified address. @@ -113,10 +113,7 @@ class CartridgeMVC : public Cartridge @param out The Serializer object to use @return False on any errors, else true */ - bool save(Serializer& out) const override - { - return false; - } + bool save(Serializer& out) const override { return false; } /** Load the current state of this cart from the given Serializer. @@ -124,49 +121,17 @@ class CartridgeMVC : public Cartridge @param in The Serializer object to use @return False on any errors, else true */ - bool load(Serializer& in) override - { - return false; - } - - /** - Install pages for the specified bank in the system. - - @param bank The bank that should be installed in the system - @param segment The segment the bank should be using - - @return true, if bank has changed - */ - bool bank(uInt16 bank, uInt16 segment = 0) override - { - return false; - } - - /** - Get the current bank. - - @param address The address to use when querying the bank - */ - uInt16 getBank(uInt16 address = 0) const override - { - return 0; - } - - /** - Query the number of banks supported by the cartridge. - */ - uInt16 romBankCount() const override - { - return 1; - } + bool load(Serializer& in) override { return false; } private: - - // Currently not used: + // Currently not used: // Pointer to a dynamically allocated ROM image of the cartridge ByteBuffer myImage{nullptr}; size_t mySize{0}; + unique_ptr myMovie; + string myPath; + private: // Following constructors and assignment operators not supported CartridgeMVC() = delete; @@ -174,12 +139,6 @@ class CartridgeMVC : public Cartridge CartridgeMVC(CartridgeMVC&&) = delete; CartridgeMVC& operator=(const CartridgeMVC&) = delete; CartridgeMVC& operator=(CartridgeMVC&&) = delete; - - private: - - unique_ptr myMovie; - string myPath; - }; #endif diff --git a/src/emucore/Serializer.cxx b/src/emucore/Serializer.cxx index 5f8dbc06d..1d45bc8d0 100644 --- a/src/emucore/Serializer.cxx +++ b/src/emucore/Serializer.cxx @@ -77,6 +77,14 @@ Serializer::Serializer() } } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void Serializer::setPosition(size_t pos) +{ + myStream->clear(); + myStream->seekg(pos); + myStream->seekp(pos); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void Serializer::rewind() { diff --git a/src/emucore/Serializer.hxx b/src/emucore/Serializer.hxx index 362977fb7..6faac1910 100644 --- a/src/emucore/Serializer.hxx +++ b/src/emucore/Serializer.hxx @@ -59,6 +59,11 @@ class Serializer */ explicit operator bool() const { return myStream != nullptr; } + /** + Sets the read/write location to the given offset in the stream. + */ + void setPosition(size_t pos); + /** Resets the read/write location to the beginning of the stream. */ @@ -220,13 +225,6 @@ class Serializer unique_ptr myStream; static constexpr uInt8 TruePattern = 0xfe, FalsePattern = 0x01; - - private: - // Following constructors and assignment operators not supported - Serializer(const Serializer&) = delete; - Serializer(Serializer&&) = delete; - Serializer& operator=(const Serializer&) = delete; - Serializer& operator=(Serializer&&) = delete; }; #endif diff --git a/src/emucore/module.mk b/src/emucore/module.mk index b061abfa9..6632729a9 100644 --- a/src/emucore/module.mk +++ b/src/emucore/module.mk @@ -47,6 +47,7 @@ MODULE_OBJS := \ src/emucore/CartFC.o \ src/emucore/CartFE.o \ src/emucore/CartMDM.o \ + src/emucore/CartMVC.o \ src/emucore/CartSB.o \ src/emucore/CartTVBoy.o \ src/emucore/CartUA.o \ From 7dabe6a7817ebf18a145677f38583175d8f2c052 Mon Sep 17 00:00:00 2001 From: Stephen Anthony Date: Thu, 22 Apr 2021 15:30:44 -0230 Subject: [PATCH 05/17] (MovieCart) Implemented left_line/right_line kernel adaptations by Thomas Jentzsch --- src/emucore/CartMVC.cxx | 168 +++++++++++++++++++++++----------------- 1 file changed, 98 insertions(+), 70 deletions(-) diff --git a/src/emucore/CartMVC.cxx b/src/emucore/CartMVC.cxx index b1884b8a0..2f57bd4c2 100644 --- a/src/emucore/CartMVC.cxx +++ b/src/emucore/CartMVC.cxx @@ -198,26 +198,49 @@ class MovieInputs #define TIMECODE_HEIGHT 12 #define MAX_LEVEL 11 #define DEFAULT_LEVEL 6 -#define BLANK_LINE_SIZE (28+3+37) // 68 +#define BLANK_LINE_SIZE (30+3+37-1) // 70-1 // #define addr_kernel_48 0x800 -#define addr_transport_buttons 0x880 -#define addr_transport_direction 0x897 -#define addr_right_line 0x94c -#define addr_left_line 0x980 -#define addr_pick_continue 0x9c2 +#define addr_right_line 0x946 +#define addr_set_aud_right 0x94a +#define addr_set_gdata9 0x94c +#define addr_set_gcol9 0x950 +#define addr_set_gdata6 0x952 +#define addr_set_gcol6 0x956 +#define addr_set_gdata5 0x95a +#define addr_set_gcol5 0x95e +#define addr_set_gdata8 0x962 +#define addr_set_gcol7 0x966 +#define addr_set_gdata7 0x96a +#define addr_set_gcol8 0x96e +// #define addr_left_line 0x980 +#define addr_set_gdata1 0x982 +#define addr_set_aud_left 0x986 +#define addr_set_gdata4 0x98a +#define addr_set_gcol4 0x98c +#define addr_set_gcol1 0x98e +#define addr_set_gdata0 0x992 +#define addr_set_gcol0 0x996 +#define addr_set_gdata3 0x99a +#define addr_set_gcol2 0x99e +#define addr_set_gdata2 0x9a2 +#define addr_set_gcol3 0x9a6 +#define addr_pick_continue 0x9b4 // #define addr_main_start 0xa00 // #define addr_aud_bank_setup 0xa0c // #define addr_tg0 0xa24 // #define addr_title_again 0xa3b +// #define addr_wait_cnt 0xa77 #define addr_end_lines 0xa80 -#define addr_end_lines_audio 0xaa1 -#define addr_set_overscan_size 0xaad -#define addr_set_vblank_size 0xac3 -#define addr_pick_transport 0xacc -#define addr_last_audio 0xacf -// #define addr_wait_lines 0xad4 -// #define addr_transport_done1 0xae7 +#define addr_set_aud_endlines 0xa8c +#define addr_set_overscan_size 0xa90 +#define addr_set_vblank_size 0xaa6 +#define addr_pick_transport 0xaaf +#define addr_transport_direction 0xab2 +#define addr_transport_buttons 0xabb +// #define addr_transport_done 0xac4 +// #define addr_wait_lines 0xac9 +// #define addr_transport_done1 0xada // #define addr_draw_title 0xb00 #define addr_title_loop 0xb50 // #define addr_black_bar 0xb52 @@ -282,9 +305,6 @@ static constexpr unsigned char kernelROM[] = { 192, 97, 99, 102, 102, 198, 198, 198, 248, 198, 248, 0, 193, 32, 48, 24, 24, 25, 24, 24, 24, 24, 126, 0, 249, 97, 97, 97, 97, 249, 0, 0, 0, 0, 0, 0, 248, 128, 128, 224, 128, 248, 255, 255, 255, 255, 255, 255, - 165, 12, 10, 173, 130, 2, 42, 41, 23, 133, 129, 133, 128, 133, 128, 133, - 128, 133, 128, 133, 128, 234, 96, 173, 128, 2, 74, 74, 74, 133, 129, 133, - 128, 133, 128, 133, 128, 133, 128, 133, 128, 133, 128, 234, 96, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, @@ -294,15 +314,18 @@ static constexpr unsigned char kernelROM[] = { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 133, 25, 133, 128, - 134, 32, 134, 33, 169, 243, 133, 27, 169, 207, 133, 28, 169, 251, 133, 27, - 169, 239, 162, 191, 160, 66, 133, 28, 169, 54, 133, 6, 134, 27, 169, 238, - 133, 7, 132, 6, 132, 28, 169, 182, 133, 6, 169, 114, 133, 7, 133, 42, - 162, 0, 162, 0, 169, 0, 162, 128, 133, 25, 134, 32, 134, 33, 169, 231, - 133, 27, 169, 159, 133, 28, 169, 253, 133, 27, 169, 247, 162, 223, 160, 242, - 133, 28, 169, 248, 133, 6, 134, 27, 169, 172, 133, 7, 132, 6, 132, 28, - 169, 216, 133, 6, 169, 98, 133, 7, 169, 0, 162, 0, 162, 0, 162, 0, - 133, 42, 76, 76, 249, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 133, 2, 133, 42, 169, 0, 162, 223, 133, 25, + 160, 98, 169, 159, 133, 28, 169, 248, 133, 7, 169, 231, 133, 27, 169, 242, + 133, 6, 169, 247, 133, 28, 169, 172, 133, 6, 169, 253, 133, 27, 169, 216, + 133, 7, 134, 27, 132, 6, 133, 43, 133, 128, 133, 128, 133, 128, 133, 42, + 133, 2, 169, 207, 133, 28, 169, 0, 133, 25, 162, 191, 160, 114, 169, 54, + 133, 7, 169, 243, 133, 27, 169, 66, 133, 6, 169, 239, 133, 28, 169, 238, + 133, 6, 169, 251, 133, 27, 169, 182, 133, 7, 134, 27, 132, 6, 169, 128, + 133, 32, 133, 33, 76, 70, 249, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, @@ -311,16 +334,16 @@ static constexpr unsigned char kernelROM[] = { 133, 2, 162, 4, 133, 128, 202, 208, 251, 133, 128, 133, 16, 133, 17, 169, 208, 133, 32, 169, 224, 133, 33, 133, 2, 133, 42, 165, 132, 106, 106, 133, 6, 133, 7, 169, 85, 133, 137, 32, 0, 251, 176, 239, 169, 0, 133, 9, - 141, 129, 2, 141, 131, 2, 169, 6, 133, 4, 169, 2, 133, 5, 169, 0, - 133, 2, 133, 128, 76, 128, 250, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 133, 37, 133, 27, 133, 16, 234, 133, 17, 133, 28, 133, 27, 133, 28, 169, + 6, 133, 4, 169, 2, 133, 5, 169, 1, 133, 38, 169, 0, 133, 32, 169, + 240, 133, 33, 133, 42, 162, 5, 202, 208, 253, 133, 43, 76, 128, 250, 255, + 160, 0, 132, 27, 132, 28, 132, 27, 169, 0, 169, 0, 169, 0, 133, 25, + 162, 29, 32, 201, 250, 169, 2, 133, 0, 162, 3, 32, 201, 250, 169, 0, + 133, 0, 169, 2, 133, 1, 162, 37, 32, 201, 250, 162, 0, 134, 1, 76, + 187, 250, 173, 128, 2, 74, 74, 74, 76, 196, 250, 165, 12, 10, 173, 130, + 2, 42, 41, 23, 133, 129, 76, 70, 249, 133, 2, 169, 0, 177, 130, 133, + 25, 165, 129, 240, 5, 198, 129, 173, 128, 20, 200, 202, 208, 235, 96, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 133, 25, 169, 0, 133, 27, 133, 28, 133, 27, 133, 28, 133, 128, 133, 128, - 133, 128, 169, 0, 133, 16, 234, 133, 17, 169, 208, 133, 32, 169, 192, 133, - 33, 169, 0, 133, 2, 133, 42, 133, 128, 133, 25, 160, 0, 162, 28, 32, - 212, 250, 169, 2, 133, 0, 162, 3, 32, 212, 250, 169, 0, 133, 0, 169, - 2, 133, 1, 162, 37, 32, 212, 250, 162, 0, 134, 1, 32, 128, 248, 169, - 0, 76, 76, 249, 177, 130, 133, 2, 133, 128, 133, 128, 133, 25, 165, 129, - 240, 5, 198, 129, 173, 128, 20, 200, 202, 208, 233, 96, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 162, 30, 32, 82, 251, 169, 2, 133, 0, 162, 3, 32, 82, 251, 169, 0, 133, 0, 169, 2, 133, 1, 162, 37, 32, 82, 251, 169, 0, 133, 1, 198, @@ -650,7 +673,7 @@ private: void stopTitleScreen(); - void writeColor(uint16_t address); + void writeColor(uint16_t address, uint8_t val); void writeAudioData(uint16_t address, uInt8 val); void writeAudio(uint16_t address); void writeGraph(uint16_t address); @@ -671,6 +694,8 @@ private: uInt8 myROM[1024]; + // full line of color + uint8_t myColor[10]; // title screen state int myTitleCycles; @@ -776,9 +801,8 @@ MovieCart::stopTitleScreen() void -MovieCart::writeColor(uint16_t address) +MovieCart::writeColor(uint16_t address, uint8_t v) { - uInt8 v = myStream.readColor(); v = (v & 0xf0) | shiftBright[(v & 0x0f) + myBright]; if (myForceColor) @@ -1013,39 +1037,43 @@ MovieCart::updateTransport() void MovieCart::fill_addr_right_line() { - writeGraph(addr_right_line + 9); // #GDATA0 - writeGraph(addr_right_line + 13); // #GDATA1 - writeGraph(addr_right_line + 17); // #GDATA2 - writeGraph(addr_right_line + 21); // #GDATA3 - writeGraph(addr_right_line + 23); // #GDATA4 + writeAudio(addr_set_aud_right + 1); + + writeGraph(addr_set_gdata5 + 1); + writeGraph(addr_set_gdata6 + 1); + writeGraph(addr_set_gdata7 + 1); + writeGraph(addr_set_gdata8 + 1); + writeGraph(addr_set_gdata9 + 1); + + writeColor(addr_set_gcol5 + 1, myColor[8]); // col 1/9 + writeColor(addr_set_gcol6 + 1, myColor[9]); // col 3/9 + writeColor(addr_set_gcol7 + 1, myColor[1]); // col 5/9 + writeColor(addr_set_gcol8 + 1, myColor[2]); // col 7/9 + writeColor(addr_set_gcol9 + 1, myColor[0]); // col 9/9 - writeColor(addr_right_line + 25); // #GCOL0 - writeColor(addr_right_line + 29); // #GCOL1 - writeColor(addr_right_line + 35); // #GCOL2 - writeColor(addr_right_line + 43); // #GCOL3 - writeColor(addr_right_line + 47); // #GCOL4 } void MovieCart::fill_addr_left_line(bool again) { - writeAudio(addr_left_line + 5); // #AUD_DATA + writeAudio(addr_set_aud_left + 1); - writeGraph(addr_left_line + 15); // #GDATA5 - writeGraph(addr_left_line + 19); // #GDATA6 - writeGraph(addr_left_line + 23); // #GDATA7 - writeGraph(addr_left_line + 27); // #GDATA8 - writeGraph(addr_left_line + 29); // #GDATA9 + writeGraph(addr_set_gdata0 + 1); + writeGraph(addr_set_gdata1 + 1); + writeGraph(addr_set_gdata2 + 1); + writeGraph(addr_set_gdata3 + 1); + writeGraph(addr_set_gdata4 + 1); - writeColor(addr_left_line + 31); // #GCOL5 - writeColor(addr_left_line + 35); // #GCOL6 - writeColor(addr_left_line + 41); // #GCOL7 - writeColor(addr_left_line + 49); // #GCOL8 - writeColor(addr_left_line + 53); // #GCOL9 + for (int i=0; i<10; i++) + myColor[i] = myStream.readColor(); - writeAudio(addr_left_line + 57); // #AUD_DATA + writeColor(addr_set_gcol0 + 1, myColor[3]); // col 0/9 + writeColor(addr_set_gcol1 + 1, myColor[4]); // col 2/9 + writeColor(addr_set_gcol2 + 1, myColor[6]); // col 4/9 + writeColor(addr_set_gcol3 + 1, myColor[7]); // col 6/9 + writeColor(addr_set_gcol4 + 1, myColor[5]); // col 8/9 - // addr_pick_line_end = 0x0ee; + // addr_pick_line_end // jmp right_line // jmp end_lines if (again) @@ -1064,19 +1092,21 @@ MovieCart::fill_addr_left_line(bool again) void MovieCart::fill_addr_end_lines() { - writeAudio(addr_end_lines_audio + 1); - myFirstAudioVal = myStream.peekAudio(); + writeAudio(addr_set_aud_endlines + 1); - // normally overscan=28, vblank=37 + if (!myOdd) + myFirstAudioVal = myStream.readAudio(); + + // normally overscan=30, vblank=37 // todo: clicky noise.. if (myOdd) { - writeROM(addr_set_overscan_size + 1, 28); + writeROM(addr_set_overscan_size + 1, 29); writeROM(addr_set_vblank_size + 1, 36); } else { - writeROM(addr_set_overscan_size + 1, 29); + writeROM(addr_set_overscan_size + 1, 30); writeROM(addr_set_vblank_size + 1, 37); } @@ -1096,8 +1126,8 @@ MovieCart::fill_addr_end_lines() void MovieCart::fill_addr_blank_lines() { - uInt8 i; - uInt8 v; + uint8_t i; + uint8_t v; // version number myStream.readVersion(); @@ -1113,7 +1143,7 @@ MovieCart::fill_addr_blank_lines() // make sure we're in sync with frame data myOdd = (v & 1); - // 28 overscan + // 30 overscan // 3 vsync // 37 vblank @@ -1128,8 +1158,6 @@ MovieCart::fill_addr_blank_lines() for (i = 0; i < (BLANK_LINE_SIZE -1); i++) writeAudio(addr_audio_bank + i); } - - writeAudio(addr_last_audio + 1); } void From f35864406c47532431afcf70c5fddd08de9d1a6a Mon Sep 17 00:00:00 2001 From: Stephen Anthony Date: Thu, 22 Apr 2021 16:07:09 -0230 Subject: [PATCH 06/17] More updates to MovieCart to match Stella style. --- src/emucore/CartMVC.cxx | 378 +++++++++++++++++----------------------- 1 file changed, 163 insertions(+), 215 deletions(-) diff --git a/src/emucore/CartMVC.cxx b/src/emucore/CartMVC.cxx index 2f57bd4c2..97ff3a7b1 100644 --- a/src/emucore/CartMVC.cxx +++ b/src/emucore/CartMVC.cxx @@ -634,123 +634,100 @@ static constexpr uInt8 levelBarsOddData[] = { class MovieCart { public: + MovieCart() = default; + ~MovieCart() = default; - MovieCart(); - ~MovieCart(); + bool init(const string& path); + bool process(uInt16 address); - bool init(const std::string& path); - bool process(uint16_t address); + uInt8 readROM(uInt16 address) const { + return myROM[address & 1023]; + } - uInt8 - readROM(uint16_t address) - { - return myROM[address & 1023]; - } + void writeROM(uInt16 address, uInt8 data) { + myROM[address & 1023] = data; + } - void - writeROM(uint16_t address, uInt8 data) - { - myROM[address & 1023] = data; - } + private: + enum Mode + { + Volume, + Bright, + Time, + Last = Time + }; -private: + enum class TitleState + { + Display, + Exiting, + Stream + }; - enum Mode - { - Volume, - Bright, - Time, - Last = Time - }; + void stopTitleScreen(); - enum TitleState - { - Display, - Exiting, - Stream - }; + void writeColor(uInt16 address, uInt8 val); + void writeAudioData(uInt16 address, uInt8 val); + void writeAudio(uInt16 address); + void writeGraph(uInt16 address); + void runStateMachine(); - void stopTitleScreen(); + void fill_addr_right_line(); + void fill_addr_left_line(bool again); + void fill_addr_end_lines(); + void fill_addr_blank_lines(); - void writeColor(uint16_t address, uint8_t val); - void writeAudioData(uint16_t address, uInt8 val); - void writeAudio(uint16_t address); - void writeGraph(uint16_t address); + void updateTransport(); - void runStateMachine(); + StreamReader myStream; - void fill_addr_right_line(); - void fill_addr_left_line(bool again); - void fill_addr_end_lines(); - void fill_addr_blank_lines(); + // data + uInt8 myROM[1024]; - void updateTransport(); + // full line of color + uInt8 myColor[10]; + // title screen state + int myTitleCycles{0}; + TitleState myTitleState{TitleState::Display}; - StreamReader myStream; + // address info + bool myA7{false}; + bool myA10{false}; + uInt8 myA10_Count{0}; - // data + // state machine info + uInt8 myState{3}; + bool myPlaying{true}; + bool myOdd{true}; + bool myBufferIndex{false}; - uInt8 myROM[1024]; + uInt8 myLines{0}; + Int32 myFrameNumber{1}; // signed - // full line of color - uint8_t myColor[10]; + uInt8 myMode{Mode::Volume}; + uInt8 myBright{DEFAULT_LEVEL}; + uInt8 myForceColor{0}; - // title screen state - int myTitleCycles; - uInt8 myTitleState; + // expressed in frames + uInt8 myDrawLevelBars{0}; + uInt8 myDrawTimeCode{0}; + MovieInputs myInputs; + MovieInputs myLastInputs; - // address info - bool myA7; - bool myA10; - uInt8 myA10_Count; - - // state machine info - - uInt8 myState; - bool myPlaying; - bool myOdd; - bool myBufferIndex; - - - uInt8 myLines; - int32_t myFrameNumber; // signed - - uInt8 myMode; - uInt8 myBright; - uInt8 myForceColor; - - // expressed in frames - uInt8 myDrawLevelBars; - uInt8 myDrawTimeCode; - - MovieInputs myInputs; - MovieInputs myLastInputs; - - int8_t mySpeed; // signed - uInt8 myJoyRepeat; - uInt8 myDirectionValue; - uInt8 myButtonsValue; - - uInt8 myVolume; - const uInt8* myVolumeScale; - uInt8 myFirstAudioVal; + Int8 mySpeed{1}; // signed + uInt8 myJoyRepeat{0}; + uInt8 myDirectionValue{0}; + uInt8 myButtonsValue{0}; + uInt8 myVolume{DEFAULT_LEVEL}; + const uInt8* myVolumeScale{scales[DEFAULT_LEVEL]}; + uInt8 myFirstAudioVal{0}; }; - -MovieCart::MovieCart() -{ -} - -MovieCart::~MovieCart() -{ -} - -bool -MovieCart::init(const std::string& path) +bool MovieCart::init(const string& path) { memcpy(myROM, kernelROM, 1024); @@ -782,10 +759,10 @@ MovieCart::init(const std::string& path) myMode = Mode::Volume; myVolume = DEFAULT_LEVEL; - myVolumeScale = scales[DEFAULT_LEVEL]; + myVolumeScale = scales[DEFAULT_LEVEL]; myBright = DEFAULT_LEVEL; - if (!myStream.open(path)) + if(!myStream.open(path)) return false; myStream.swapField(true); @@ -793,15 +770,13 @@ MovieCart::init(const std::string& path) return true; } -void -MovieCart::stopTitleScreen() +void MovieCart::stopTitleScreen() { - writeROM(addr_title_loop + 0, 0x18); // clear carry, one bit difference from 0x38 sec + // clear carry, one bit difference from 0x38 sec + writeROM(addr_title_loop + 0, 0x18); } - -void -MovieCart::writeColor(uint16_t address, uint8_t v) +void MovieCart::writeColor(uInt16 address, uInt8 v) { v = (v & 0xf0) | shiftBright[(v & 0x0f) + myBright]; @@ -813,59 +788,50 @@ MovieCart::writeColor(uint16_t address, uint8_t v) writeROM(address, v); } -void -MovieCart::writeAudioData(uint16_t address, uInt8 val) +void MovieCart::writeAudioData(uInt16 address, uInt8 val) { - uInt8 v; - v = myVolumeScale[val]; - writeROM(address, v); + writeROM(address, myVolumeScale[val]); } -void -MovieCart::writeAudio(uint16_t address) +void MovieCart::writeAudio(uInt16 address) { - uInt8 v = myStream.readAudio(); - writeAudioData(address, v); + writeAudioData(address, myStream.readAudio()); } -void -MovieCart::writeGraph(uint16_t address) +void MovieCart::writeGraph(uInt16 address) { - uInt8 v = myStream.readGraph(); - writeROM(address, v); + writeROM(address, myStream.readGraph()); } -void -MovieCart::updateTransport() +void MovieCart::updateTransport() { myStream.overrideGraph(nullptr); - - // have to cut rate in half, to remove glitches...todo.. + // have to cut rate in half, to remove glitches...todo.. + { + if(myBufferIndex) { - if (myBufferIndex == true) - { uInt8 temp = ~(myA10_Count & 0x1e) & 0x1e; - if (temp == myDirectionValue) + if (temp == myDirectionValue) myInputs.updateDirection(temp); - myDirectionValue = temp; - } - else - { + myDirectionValue = temp; + } + else + { uInt8 temp = ~(myA10_Count & 0x17) & 0x17; - if (temp == myButtonsValue) + if(temp == myButtonsValue) myInputs.updateTransport(temp); - myButtonsValue = temp; - } - - myA10_Count = 0; + myButtonsValue = temp; } - if (myInputs.reset) + myA10_Count = 0; + } + + if(myInputs.reset) { myFrameNumber = 1; myPlaying = true; @@ -878,14 +844,14 @@ MovieCart::updateTransport() uInt8 lastMainMode = myMode; - if (myInputs.up && !myLastInputs.up) + if(myInputs.up && !myLastInputs.up) { - if (myMode == 0) + if(myMode == 0) myMode = Mode::Last; else myMode--; } - else if (myInputs.down && !myLastInputs.down) + else if(myInputs.down && !myLastInputs.down) { if (myMode == Mode::Last) myMode = 0; @@ -893,7 +859,7 @@ MovieCart::updateTransport() myMode++; } - if (myInputs.left || myInputs.right) + if(myInputs.left || myInputs.right) { myJoyRepeat++; } @@ -903,24 +869,23 @@ MovieCart::updateTransport() mySpeed = 1; } - - if (myJoyRepeat & 16) + if(myJoyRepeat & 16) { myJoyRepeat = 0; - if (myInputs.left || myInputs.right) + if(myInputs.left || myInputs.right) { - if (myMode == Mode::Time) + if(myMode == Mode::Time) { myDrawTimeCode = OSD_FRAMES; mySpeed += 4; if (mySpeed < 0) mySpeed -= 4; } - else if (myMode == Mode::Volume) + else if(myMode == Mode::Volume) { myDrawLevelBars = OSD_FRAMES; - if (myInputs.left) + if(myInputs.left) { if (myVolume) myVolume--; @@ -928,30 +893,29 @@ MovieCart::updateTransport() else { myVolume++; - if (myVolume >= MAX_LEVEL) + if(myVolume >= MAX_LEVEL) myVolume--; } } - else if (myMode == Mode::Bright) + else if(myMode == Mode::Bright) { myDrawLevelBars = OSD_FRAMES; - if (myInputs.left) + if(myInputs.left) { - if (myBright) + if(myBright) myBright--; } else { myBright++; - if (myBright >= MAX_LEVEL) + if(myBright >= MAX_LEVEL) myBright--; } } } } - - if (myInputs.select && !myLastInputs.select) + if(myInputs.select && !myLastInputs.select) { myDrawTimeCode = OSD_FRAMES; myFrameNumber -= 60 * BACK_SECONDS + 1; @@ -960,46 +924,45 @@ MovieCart::updateTransport() return; } - if (myInputs.fire && !myLastInputs.fire) + if(myInputs.fire && !myLastInputs.fire) myPlaying = !myPlaying; - switch (myMode) + switch(myMode) { case Mode::Time: - if (lastMainMode != myMode) + if(lastMainMode != myMode) myDrawTimeCode = OSD_FRAMES; break; case Mode::Bright: case Mode::Volume: default: - if (lastMainMode != myMode) + if(lastMainMode != myMode) myDrawLevelBars = OSD_FRAMES; break; } // just draw one - if (myDrawLevelBars > myDrawTimeCode) + if(myDrawLevelBars > myDrawTimeCode) myDrawTimeCode = 0; else myDrawLevelBars = 0; - if (myPlaying) + if(myPlaying) myVolumeScale = scales[myVolume]; else myVolumeScale = scales[0]; // update frame + Int8 step = 1; - int8_t step = 1; - - if (!myPlaying) // step while paused + if(!myPlaying) // step while paused { - if (myMode == Mode::Time) + if(myMode == Mode::Time) { - if (myInputs.right && !myLastInputs.right) + if(myInputs.right && !myLastInputs.right) step = 3; - else if (myInputs.left && !myLastInputs.left) + else if(myInputs.left && !myLastInputs.left) step = -3; else step = (myFrameNumber & 1) ? -1 : 1; @@ -1011,9 +974,9 @@ MovieCart::updateTransport() } else { - if (myMode == Mode::Time) + if(myMode == Mode::Time) { - if (myInputs.right) + if(myInputs.right) step = mySpeed; else if (myInputs.left) step = -mySpeed; @@ -1025,7 +988,7 @@ MovieCart::updateTransport() } myFrameNumber += step; - if (myFrameNumber < 1) + if(myFrameNumber < 1) { myFrameNumber = 1; mySpeed = 1; @@ -1034,8 +997,7 @@ MovieCart::updateTransport() myLastInputs = myInputs; } -void -MovieCart::fill_addr_right_line() +void MovieCart::fill_addr_right_line() { writeAudio(addr_set_aud_right + 1); @@ -1053,8 +1015,7 @@ MovieCart::fill_addr_right_line() } -void -MovieCart::fill_addr_left_line(bool again) +void MovieCart::fill_addr_left_line(bool again) { writeAudio(addr_set_aud_left + 1); @@ -1064,7 +1025,7 @@ MovieCart::fill_addr_left_line(bool again) writeGraph(addr_set_gdata3 + 1); writeGraph(addr_set_gdata4 + 1); - for (int i=0; i<10; i++) + for(int i = 0; i < 10; ++i) myColor[i] = myStream.readColor(); writeColor(addr_set_gcol0 + 1, myColor[3]); // col 0/9 @@ -1076,7 +1037,7 @@ MovieCart::fill_addr_left_line(bool again) // addr_pick_line_end // jmp right_line // jmp end_lines - if (again) + if(again) { writeROM(addr_pick_continue + 1, LO_JUMP_BYTE(addr_right_line)); writeROM(addr_pick_continue + 2, HI_JUMP_BYTE(addr_right_line)); @@ -1088,18 +1049,16 @@ MovieCart::fill_addr_left_line(bool again) } } - -void -MovieCart::fill_addr_end_lines() +void MovieCart::fill_addr_end_lines() { writeAudio(addr_set_aud_endlines + 1); - if (!myOdd) + if(!myOdd) myFirstAudioVal = myStream.readAudio(); // normally overscan=30, vblank=37 // todo: clicky noise.. - if (myOdd) + if(myOdd) { writeROM(addr_set_overscan_size + 1, 29); writeROM(addr_set_vblank_size + 1, 36); @@ -1110,7 +1069,7 @@ MovieCart::fill_addr_end_lines() writeROM(addr_set_vblank_size + 1, 37); } - if (myBufferIndex == false) + if(!myBufferIndex) { writeROM(addr_pick_transport + 1, LO_JUMP_BYTE(addr_transport_direction)); writeROM(addr_pick_transport + 2, HI_JUMP_BYTE(addr_transport_direction)); @@ -1123,12 +1082,8 @@ MovieCart::fill_addr_end_lines() } -void -MovieCart::fill_addr_blank_lines() +void MovieCart::fill_addr_blank_lines() { - uint8_t i; - uint8_t v; - // version number myStream.readVersion(); myStream.readVersion(); @@ -1138,7 +1093,7 @@ MovieCart::fill_addr_blank_lines() // frame number myStream.readFrame(); myStream.readFrame(); - v = myStream.readFrame(); + uInt8 v = myStream.readFrame(); // make sure we're in sync with frame data myOdd = (v & 1); @@ -1147,30 +1102,29 @@ MovieCart::fill_addr_blank_lines() // 3 vsync // 37 vblank - if (myOdd) + if(myOdd) { writeAudioData(addr_audio_bank + 0, myFirstAudioVal); - for (i = 1; i < (BLANK_LINE_SIZE + 1); i++) + for(uInt8 i = 1; i < (BLANK_LINE_SIZE + 1); i++) writeAudio(addr_audio_bank + i); } else { - for (i = 0; i < (BLANK_LINE_SIZE -1); i++) + for(uInt8 i = 0; i < (BLANK_LINE_SIZE -1); i++) writeAudio(addr_audio_bank + i); } } -void -MovieCart::runStateMachine() +void MovieCart::runStateMachine() { switch(myState) { case 1: - if (myA7) + if(myA7) { - if (myLines == (TIMECODE_HEIGHT-1)) + if(myLines == (TIMECODE_HEIGHT-1)) { - if (myDrawTimeCode) + if(myDrawTimeCode) { myDrawTimeCode--; myForceColor = COLOR_BLUE; @@ -1179,21 +1133,21 @@ MovieCart::runStateMachine() } // label = 12, bars = 7 - if (myLines == 21) + if(myLines == 21) { - if (myDrawLevelBars) + if(myDrawLevelBars) { myDrawLevelBars--; myForceColor = COLOR_BLUE; - switch (myMode) + switch(myMode) { case Mode::Time: myStream.overrideGraph(nullptr); break; case Mode::Bright: - if (myOdd) + if(myOdd) myStream.overrideGraph(brightLabelOdd); else myStream.overrideGraph(brightLabelEven); @@ -1201,7 +1155,7 @@ MovieCart::runStateMachine() case Mode::Volume: default: - if (myOdd) + if(myOdd) myStream.overrideGraph(volumeLabelOdd); else myStream.overrideGraph(volumeLabelEven); @@ -1210,13 +1164,13 @@ MovieCart::runStateMachine() } } - if (myLines == 7) + if(myLines == 7) { - if (myDrawLevelBars) + if(myDrawLevelBars) { - uInt8 levelValue; + uInt8 levelValue = 0; - switch (myMode) + switch(myMode) { case Mode::Time: levelValue = 0; @@ -1232,7 +1186,7 @@ MovieCart::runStateMachine() break; } - if (myOdd) + if(myOdd) myStream.overrideGraph(&levelBarsOddData[levelValue * 40]); else myStream.overrideGraph(&levelBarsEvenData[levelValue * 40]); @@ -1246,11 +1200,10 @@ MovieCart::runStateMachine() } break; - case 2: - if (!myA7) + if(!myA7) { - if (myLines >= 1) + if(myLines >= 1) { fill_addr_left_line(1); @@ -1274,10 +1227,11 @@ MovieCart::runStateMachine() break; case 3: - if (myA7) + if(myA7) { // hit end? rewind just before end - while (myFrameNumber >= 2 && !myStream.readField(myFrameNumber, myBufferIndex)) + while (myFrameNumber >= 2 && + !myStream.readField(myFrameNumber, myBufferIndex)) { myFrameNumber -= 2; myJoyRepeat = 0; @@ -1294,28 +1248,26 @@ MovieCart::runStateMachine() } } -bool -MovieCart::process(uint16_t address) +bool MovieCart::process(uInt16 address) { - bool a12 = (address & (1 << 12)) ? 1:0; bool a11 = (address & (1 << 11)) ? 1:0; // count a10 pulses bool a10i = (address & (1 << 10)); - if (a10i && !myA10) + if(a10i && !myA10) myA10_Count++; myA10 = a10i; // latch a7 state - if (a11) // a12 + if(a11) // a12 myA7 = (address & (1 << 7)); // each 128 switch(myTitleState) { case TitleState::Display: myTitleCycles++; - if (myTitleCycles == TITLE_CYCLES) + if(myTitleCycles == TITLE_CYCLES) { stopTitleScreen(); myTitleState = TitleState::Exiting; @@ -1324,7 +1276,7 @@ MovieCart::process(uint16_t address) break; case TitleState::Exiting: - if (myA7) + if(myA7) myTitleState = TitleState::Stream; break; @@ -1362,10 +1314,6 @@ void CartridgeMVC::install(System& system) // Map all of the accesses to call peek and poke System::PageAccess access(this, System::PageAccessType::READWRITE); - - access.directPeekBase = nullptr; - access.directPokeBase = nullptr; - for(uInt16 addr = 0x1000; addr < 0x2000; addr += System::PAGE_SIZE) mySystem->setPageAccess(addr, access); } From 0a2e25cdecba934b6f54d81782d90fd59e718f1a Mon Sep 17 00:00:00 2001 From: Stephen Anthony Date: Thu, 22 Apr 2021 20:08:14 -0230 Subject: [PATCH 07/17] A few more formatting cleanups. --- src/emucore/CartMVC.cxx | 63 ++++++++++++++++++----------------------- 1 file changed, 28 insertions(+), 35 deletions(-) diff --git a/src/emucore/CartMVC.cxx b/src/emucore/CartMVC.cxx index 97ff3a7b1..392233a47 100644 --- a/src/emucore/CartMVC.cxx +++ b/src/emucore/CartMVC.cxx @@ -105,9 +105,7 @@ class StreamReader return myGraphOverride ? *myGraphOverride++ : *myGraph++; } - void overrideGraph(const uInt8* p) { - myGraphOverride = p; - } + void overrideGraph(const uInt8* p) { myGraphOverride = p; } uInt8 readAudio() { return *myAudio++; } @@ -635,7 +633,6 @@ class MovieCart { public: MovieCart() = default; - ~MovieCart() = default; bool init(const string& path); bool process(uInt16 address); @@ -664,12 +661,21 @@ class MovieCart Stream }; - void stopTitleScreen(); + void stopTitleScreen() { + // clear carry, one bit difference from 0x38 sec + writeROM(addr_title_loop + 0, 0x18); + } void writeColor(uInt16 address, uInt8 val); - void writeAudioData(uInt16 address, uInt8 val); - void writeAudio(uInt16 address); - void writeGraph(uInt16 address); + void writeAudioData(uInt16 address, uInt8 val) { + writeROM(address, myVolumeScale[val]); + } + void writeAudio(uInt16 address) { + writeAudioData(address, myStream.readAudio()); + } + void writeGraph(uInt16 address) { + writeROM(address, myStream.readGraph()); + } void runStateMachine(); @@ -727,6 +733,7 @@ class MovieCart uInt8 myFirstAudioVal{0}; }; +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool MovieCart::init(const string& path) { memcpy(myROM, kernelROM, 1024); @@ -770,39 +777,20 @@ bool MovieCart::init(const string& path) return true; } -void MovieCart::stopTitleScreen() -{ - // clear carry, one bit difference from 0x38 sec - writeROM(addr_title_loop + 0, 0x18); -} - +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void MovieCart::writeColor(uInt16 address, uInt8 v) { v = (v & 0xf0) | shiftBright[(v & 0x0f) + myBright]; - if (myForceColor) + if(myForceColor) v = myForceColor; - if (myInputs.bw) + if(myInputs.bw) v &= 0x0f; writeROM(address, v); } -void MovieCart::writeAudioData(uInt16 address, uInt8 val) -{ - writeROM(address, myVolumeScale[val]); -} - -void MovieCart::writeAudio(uInt16 address) -{ - writeAudioData(address, myStream.readAudio()); -} - -void MovieCart::writeGraph(uInt16 address) -{ - writeROM(address, myStream.readGraph()); -} - +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void MovieCart::updateTransport() { myStream.overrideGraph(nullptr); @@ -997,6 +985,7 @@ void MovieCart::updateTransport() myLastInputs = myInputs; } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void MovieCart::fill_addr_right_line() { writeAudio(addr_set_aud_right + 1); @@ -1015,6 +1004,7 @@ void MovieCart::fill_addr_right_line() } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void MovieCart::fill_addr_left_line(bool again) { writeAudio(addr_set_aud_left + 1); @@ -1049,6 +1039,7 @@ void MovieCart::fill_addr_left_line(bool again) } } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void MovieCart::fill_addr_end_lines() { writeAudio(addr_set_aud_endlines + 1); @@ -1079,9 +1070,9 @@ void MovieCart::fill_addr_end_lines() writeROM(addr_pick_transport + 1, LO_JUMP_BYTE(addr_transport_buttons)); writeROM(addr_pick_transport + 2, HI_JUMP_BYTE(addr_transport_buttons)); } - } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void MovieCart::fill_addr_blank_lines() { // version number @@ -1115,6 +1106,7 @@ void MovieCart::fill_addr_blank_lines() } } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void MovieCart::runStateMachine() { switch(myState) @@ -1248,6 +1240,7 @@ void MovieCart::runStateMachine() } } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool MovieCart::process(uInt16 address) { bool a12 = (address & (1 << 12)) ? 1:0; @@ -1293,9 +1286,9 @@ CartridgeMVC::CartridgeMVC(const string& path, size_t size, const string& md5, const Settings& settings, size_t bsSize) : Cartridge(settings, md5), - mySize{bsSize} + mySize{bsSize}, + myPath{path} { - myPath = path; myMovie = make_unique(); // not used @@ -1328,7 +1321,7 @@ void CartridgeMVC::reset() const ByteBuffer& CartridgeMVC::getImage(size_t& size) const { // not used - size = mySize; + size = 0; return myImage; } From c19a86147a4deaf9aecbb911f3e088329f9c46a7 Mon Sep 17 00:00:00 2001 From: Stephen Anthony Date: Fri, 23 Apr 2021 15:08:49 -0230 Subject: [PATCH 08/17] Added support for Mac. --- src/macos/stella.xcodeproj/project.pbxproj | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/macos/stella.xcodeproj/project.pbxproj b/src/macos/stella.xcodeproj/project.pbxproj index 765d3a39a..4784e16be 100644 --- a/src/macos/stella.xcodeproj/project.pbxproj +++ b/src/macos/stella.xcodeproj/project.pbxproj @@ -451,6 +451,8 @@ DC8C1BB114B25DE7006440EE /* MindLink.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC8C1BAB14B25DE7006440EE /* MindLink.cxx */; }; DC8C1BB214B25DE7006440EE /* MindLink.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC8C1BAC14B25DE7006440EE /* MindLink.hxx */; }; DC8CF9BD17C15A27004B533D /* ConsoleMediumFont.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC8CF9BC17C15A27004B533D /* ConsoleMediumFont.hxx */; }; + DC911C7526333B9200666AC0 /* CartMVC.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC911C7326333B9100666AC0 /* CartMVC.cxx */; }; + DC911C7626333B9200666AC0 /* CartMVC.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC911C7426333B9100666AC0 /* CartMVC.hxx */; }; DC932D440F278A5200FEFEFC /* DefProps.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC932D3F0F278A5200FEFEFC /* DefProps.hxx */; }; DC932D450F278A5200FEFEFC /* Serializable.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC932D400F278A5200FEFEFC /* Serializable.hxx */; }; DC932D460F278A5200FEFEFC /* SerialPort.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC932D410F278A5200FEFEFC /* SerialPort.hxx */; }; @@ -1258,6 +1260,8 @@ DC8C1BAB14B25DE7006440EE /* MindLink.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MindLink.cxx; sourceTree = ""; }; DC8C1BAC14B25DE7006440EE /* MindLink.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = MindLink.hxx; sourceTree = ""; }; DC8CF9BC17C15A27004B533D /* ConsoleMediumFont.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ConsoleMediumFont.hxx; sourceTree = ""; }; + DC911C7326333B9100666AC0 /* CartMVC.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CartMVC.cxx; sourceTree = ""; }; + DC911C7426333B9100666AC0 /* CartMVC.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CartMVC.hxx; sourceTree = ""; }; DC932D3F0F278A5200FEFEFC /* DefProps.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = DefProps.hxx; sourceTree = ""; }; DC932D400F278A5200FEFEFC /* Serializable.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Serializable.hxx; sourceTree = ""; }; DC932D410F278A5200FEFEFC /* SerialPort.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = SerialPort.hxx; sourceTree = ""; }; @@ -2044,6 +2048,8 @@ DC6A18FB19B3E67A00DEB242 /* CartMDM.hxx */, DC71EA9B1FDA06D2008827CB /* CartMNetwork.cxx */, DC71EA9C1FDA06D2008827CB /* CartMNetwork.hxx */, + DC911C7326333B9100666AC0 /* CartMVC.cxx */, + DC911C7426333B9100666AC0 /* CartMVC.hxx */, DC0984830D3985160073C852 /* CartSB.cxx */, DC0984840D3985160073C852 /* CartSB.hxx */, DC84397A247B294D00C6A4FC /* CartTVBoy.cxx */, @@ -2922,6 +2928,7 @@ DC3EE8631E2C0E6D00905161 /* inffast.h in Headers */, DC676A501729A0B000E4E73D /* CartE0Widget.hxx in Headers */, DC676A521729A0B000E4E73D /* CartE7Widget.hxx in Headers */, + DC911C7626333B9200666AC0 /* CartMVC.hxx in Headers */, DC676A541729A0B000E4E73D /* CartFA2Widget.hxx in Headers */, DC676A561729A0B000E4E73D /* CartFEWidget.hxx in Headers */, DC676A5A1729A0B000E4E73D /* CartSBWidget.hxx in Headers */, @@ -3394,6 +3401,7 @@ DCAACAFE188D631500A4D282 /* CartDFSC.cxx in Sources */, DCAACB0E188D636F00A4D282 /* Cart4KSCWidget.cxx in Sources */, DCB60AD02543100900A5C1D2 /* FBBackendSDL2.cxx in Sources */, + DC911C7526333B9200666AC0 /* CartMVC.cxx in Sources */, DCAACB10188D636F00A4D282 /* CartBFSCWidget.cxx in Sources */, DCC2FDF6255EB82500FA5E81 /* ToolTip.cxx in Sources */, DCAACB12188D636F00A4D282 /* CartBFWidget.cxx in Sources */, From 435bf7cb8a1531f52d65880912baf3c63a857f7c Mon Sep 17 00:00:00 2001 From: Stephen Anthony Date: Fri, 23 Apr 2021 18:00:44 -0230 Subject: [PATCH 09/17] Fix crash in debugger. Much more work still required here. --- src/emucore/CartMVC.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/emucore/CartMVC.cxx b/src/emucore/CartMVC.cxx index 392233a47..41f227009 100644 --- a/src/emucore/CartMVC.cxx +++ b/src/emucore/CartMVC.cxx @@ -1321,7 +1321,7 @@ void CartridgeMVC::reset() const ByteBuffer& CartridgeMVC::getImage(size_t& size) const { // not used - size = 0; + size = mySize; return myImage; } From fb164fb740709c99d7b2232630fadf011a1d4d6e Mon Sep 17 00:00:00 2001 From: Lo Def Date: Sat, 24 Apr 2021 23:46:46 -0400 Subject: [PATCH 10/17] (MovieCart) Avoid unnecessary shuffling of color data during encoding and decoding, as new kernel does not require it. --- src/emucore/CartMVC.cxx | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/src/emucore/CartMVC.cxx b/src/emucore/CartMVC.cxx index 392233a47..ca72ac77e 100644 --- a/src/emucore/CartMVC.cxx +++ b/src/emucore/CartMVC.cxx @@ -666,7 +666,7 @@ class MovieCart writeROM(addr_title_loop + 0, 0x18); } - void writeColor(uInt16 address, uInt8 val); + void writeColor(uInt16 address); void writeAudioData(uInt16 address, uInt8 val) { writeROM(address, myVolumeScale[val]); } @@ -691,9 +691,6 @@ class MovieCart // data uInt8 myROM[1024]; - // full line of color - uInt8 myColor[10]; - // title screen state int myTitleCycles{0}; TitleState myTitleState{TitleState::Display}; @@ -778,8 +775,10 @@ bool MovieCart::init(const string& path) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void MovieCart::writeColor(uInt16 address, uInt8 v) +void MovieCart::writeColor(uInt16 address) { + uint8_t v = myStream.readColor(); + v = (v & 0xf0) | shiftBright[(v & 0x0f) + myBright]; if(myForceColor) @@ -996,11 +995,11 @@ void MovieCart::fill_addr_right_line() writeGraph(addr_set_gdata8 + 1); writeGraph(addr_set_gdata9 + 1); - writeColor(addr_set_gcol5 + 1, myColor[8]); // col 1/9 - writeColor(addr_set_gcol6 + 1, myColor[9]); // col 3/9 - writeColor(addr_set_gcol7 + 1, myColor[1]); // col 5/9 - writeColor(addr_set_gcol8 + 1, myColor[2]); // col 7/9 - writeColor(addr_set_gcol9 + 1, myColor[0]); // col 9/9 + writeColor(addr_set_gcol5 + 1); + writeColor(addr_set_gcol6 + 1); + writeColor(addr_set_gcol7 + 1); + writeColor(addr_set_gcol8 + 1); + writeColor(addr_set_gcol9 + 1); } @@ -1015,14 +1014,11 @@ void MovieCart::fill_addr_left_line(bool again) writeGraph(addr_set_gdata3 + 1); writeGraph(addr_set_gdata4 + 1); - for(int i = 0; i < 10; ++i) - myColor[i] = myStream.readColor(); - - writeColor(addr_set_gcol0 + 1, myColor[3]); // col 0/9 - writeColor(addr_set_gcol1 + 1, myColor[4]); // col 2/9 - writeColor(addr_set_gcol2 + 1, myColor[6]); // col 4/9 - writeColor(addr_set_gcol3 + 1, myColor[7]); // col 6/9 - writeColor(addr_set_gcol4 + 1, myColor[5]); // col 8/9 + writeColor(addr_set_gcol0 + 1); + writeColor(addr_set_gcol1 + 1); + writeColor(addr_set_gcol2 + 1); + writeColor(addr_set_gcol3 + 1); + writeColor(addr_set_gcol4 + 1); // addr_pick_line_end // jmp right_line From 9ac88c66626329fbb9173f4958b1192082876aad Mon Sep 17 00:00:00 2001 From: Stephen Anthony Date: Mon, 3 May 2021 20:35:11 -0230 Subject: [PATCH 11/17] Move detection of MVC file out of FSNode class. There are several reasons for this: - It more properly belongs in the class actually opening the ROM, since FSNode can represent more than just ROM files. - Some ports don't have proper FSNode support, so MVC would break there. - In general, it makes FSNode::read more general, able to read partial files. --- src/common/FSNodeZIP.cxx | 4 ++-- src/common/FSNodeZIP.hxx | 4 ++-- src/emucore/Bankswitch.hxx | 2 +- src/emucore/CartDetector.cxx | 28 ++++++++++++++-------------- src/emucore/CartDetector.hxx | 6 +++--- src/emucore/CartMVC.cxx | 12 ++++++++++++ src/emucore/CartMVC.hxx | 6 +++--- src/emucore/FSNode.cxx | 12 ++++-------- src/emucore/FSNode.hxx | 6 ++++-- src/emucore/OSystem.cxx | 11 ++++++++++- src/emucore/Serializer.cxx | 10 +++++++--- src/emucore/Serializer.hxx | 4 ++-- 12 files changed, 64 insertions(+), 41 deletions(-) diff --git a/src/common/FSNodeZIP.cxx b/src/common/FSNodeZIP.cxx index 754f848d6..f7720d72e 100644 --- a/src/common/FSNodeZIP.cxx +++ b/src/common/FSNodeZIP.cxx @@ -180,7 +180,7 @@ bool FilesystemNodeZIP::getChildren(AbstractFSList& myList, ListMode mode) const } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -size_t FilesystemNodeZIP::read(ByteBuffer& image) const +size_t FilesystemNodeZIP::read(ByteBuffer& image, size_t) const { switch(_error) { @@ -205,7 +205,7 @@ size_t FilesystemNodeZIP::read(stringstream& image) const // For now, we just read into a buffer and store in the stream // TODO: maybe there's a more efficient way to do this? ByteBuffer buffer; - size_t size = read(buffer); + size_t size = read(buffer, 0); if(size > 0) image.write(reinterpret_cast(buffer.get()), size); diff --git a/src/common/FSNodeZIP.hxx b/src/common/FSNodeZIP.hxx index 77246d35f..7747b7acc 100644 --- a/src/common/FSNodeZIP.hxx +++ b/src/common/FSNodeZIP.hxx @@ -62,8 +62,8 @@ class FilesystemNodeZIP : public AbstractFSNode bool getChildren(AbstractFSList& list, ListMode mode) const override; AbstractFSNodePtr getParent() const override; - size_t read(ByteBuffer& image) const override; - size_t read(stringstream& image) const override; + size_t read(ByteBuffer& buffer, size_t size) const override; + size_t read(stringstream& buffer) const override; size_t write(const ByteBuffer& buffer, size_t size) const override; size_t write(const stringstream& buffer) const override; diff --git a/src/emucore/Bankswitch.hxx b/src/emucore/Bankswitch.hxx index 2070ace36..38485d2ea 100644 --- a/src/emucore/Bankswitch.hxx +++ b/src/emucore/Bankswitch.hxx @@ -45,7 +45,7 @@ class Bankswitch _DPCP, _E0, _E7, _E78K, _EF, _EFSC, _F0, _F4, _F4SC, _F6, _F6SC, _F8, _F8SC, _FA, _FA2, _FC, _FE, _MDM, _MVC, _SB, _TVBOY, - _UA, _UASW, _WD, _WDSW, _X07, + _UA, _UASW, _WD, _WDSW, _X07, #ifdef CUSTOM_ARM _CUSTOM, #endif diff --git a/src/emucore/CartDetector.cxx b/src/emucore/CartDetector.cxx index 3414d5be9..d3206631b 100644 --- a/src/emucore/CartDetector.cxx +++ b/src/emucore/CartDetector.cxx @@ -697,31 +697,31 @@ bool CartDetector::isProbablyMVC(const ByteBuffer& image, size_t size) { // MVC version 0 uInt8 sig[] = { 'M', 'V', 'C', 0 }; - int sigSize = sizeof(sig); + int sigSize = sizeof(sig); return searchForBytes(image, std::min(size, sigSize+1), sig, sigSize); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -size_t CartDetector::isProbablyMVC(std::istream &in, size_t maxSize) +size_t CartDetector::isProbablyMVC(const FilesystemNode& rom) { - const size_t frameSize = 2 * CartridgeMVC::MVC_FIELD_PAD_SIZE; - bool found = false; + constexpr size_t frameSize = 2 * CartridgeMVC::MVC_FIELD_PAD_SIZE; - // Returns size of field if stream is probably an MVC movie cartridge + if(Bankswitch::typeFromExtension(rom) == Bankswitch::Type::_MVC) + return frameSize; - if (maxSize >= frameSize) + Serializer s(rom.getPath(), Serializer::Mode::ReadOnly); + if(s) { - auto pos = in.tellg(); + if(s.size() < frameSize) + return 0; - ByteBuffer image = make_unique(frameSize); - in.read(reinterpret_cast(image.get()), frameSize); + uInt8 image[frameSize]; + s.getByteArray(image, frameSize); - in.seekg(pos); - - found = isProbablyMVC(image, frameSize); + uInt8 sig[] = { 'M', 'V', 'C', 0 }; // MVC version 0 + return searchForBytes(image, frameSize, sig, 4) ? frameSize : 0; } - - return found ? frameSize : 0; + return 0; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/emucore/CartDetector.hxx b/src/emucore/CartDetector.hxx index d845dad78..dc9025c76 100644 --- a/src/emucore/CartDetector.hxx +++ b/src/emucore/CartDetector.hxx @@ -19,6 +19,7 @@ #define CARTRIDGE_DETECTOR_HXX #include "Bankswitch.hxx" +#include "FSNode.hxx" #include "bspf.hxx" /** @@ -40,12 +41,11 @@ class CartDetector */ static Bankswitch::Type autodetectType(const ByteBuffer& image, size_t size); - /** - MVC cartridges are of arbitary large length + MVC cartridges are of arbitary large length Returns size of frame if stream is probably an MVC movie cartridge */ - static size_t isProbablyMVC(std::istream &in, size_t size); + static size_t isProbablyMVC(const FilesystemNode& rom); private: /** diff --git a/src/emucore/CartMVC.cxx b/src/emucore/CartMVC.cxx index 835090424..0562bca00 100644 --- a/src/emucore/CartMVC.cxx +++ b/src/emucore/CartMVC.cxx @@ -1340,3 +1340,15 @@ bool CartridgeMVC::poke(uInt16 address, uInt8 value) { return myMovie->process(address); } + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool CartridgeMVC::save(Serializer& out) const +{ + return false; // TODO: implement this +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool CartridgeMVC::load(Serializer& in) +{ + return false; // TODO: implement this +} diff --git a/src/emucore/CartMVC.hxx b/src/emucore/CartMVC.hxx index 3bac2e239..c03101b52 100644 --- a/src/emucore/CartMVC.hxx +++ b/src/emucore/CartMVC.hxx @@ -51,7 +51,7 @@ class CartridgeMVC : public Cartridge @param bsSize The size specified by the bankswitching scheme */ CartridgeMVC(const string& path, size_t size, const string& md5, - const Settings& settings, size_t bsSize = 1_KB); + const Settings& settings, size_t bsSize = 8_KB); ~CartridgeMVC() override; /** @@ -113,7 +113,7 @@ class CartridgeMVC : public Cartridge @param out The Serializer object to use @return False on any errors, else true */ - bool save(Serializer& out) const override { return false; } + bool save(Serializer& out) const override; /** Load the current state of this cart from the given Serializer. @@ -121,7 +121,7 @@ class CartridgeMVC : public Cartridge @param in The Serializer object to use @return False on any errors, else true */ - bool load(Serializer& in) override { return false; } + bool load(Serializer& in) override; private: // Currently not used: diff --git a/src/emucore/FSNode.cxx b/src/emucore/FSNode.cxx index 28a6100f5..f240ebadc 100644 --- a/src/emucore/FSNode.cxx +++ b/src/emucore/FSNode.cxx @@ -333,7 +333,7 @@ bool FilesystemNode::rename(const string& newfile) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -size_t FilesystemNode::read(ByteBuffer& buffer) const +size_t FilesystemNode::read(ByteBuffer& buffer, size_t size) const { size_t sizeRead = 0; @@ -342,7 +342,7 @@ size_t FilesystemNode::read(ByteBuffer& buffer) const throw runtime_error("File not found/readable"); // First let the private subclass attempt to open the file - if (_realNode && (sizeRead = _realNode->read(buffer)) > 0) + if (_realNode && (sizeRead = _realNode->read(buffer, size)) > 0) return sizeRead; // Otherwise, the default behaviour is to read from a normal C++ ifstream @@ -355,12 +355,8 @@ size_t FilesystemNode::read(ByteBuffer& buffer) const if (sizeRead == 0) throw runtime_error("Zero-byte file"); - - // In the case of MVC (MovieCart) files, contents are streaming data - // of arbitrary length, so just read first frame. - size_t subSize = CartDetector::isProbablyMVC(in, sizeRead); - if (subSize > 0) - sizeRead = subSize; + else if (size != 0) + sizeRead = size; buffer = make_unique(sizeRead); in.read(reinterpret_cast(buffer.get()), sizeRead); diff --git a/src/emucore/FSNode.hxx b/src/emucore/FSNode.hxx index d2b9fbc00..8cb84944e 100644 --- a/src/emucore/FSNode.hxx +++ b/src/emucore/FSNode.hxx @@ -244,12 +244,13 @@ class FilesystemNode * Read data (binary format) into the given buffer. * * @param buffer The buffer to contain the data (allocated in this method). + * @param size The amount of data to read (0 means read all data). * * @return The number of bytes read (0 in the case of failure) * This method can throw exceptions, and should be used inside * a try-catch block. */ - size_t read(ByteBuffer& buffer) const; + size_t read(ByteBuffer& buffer, size_t size = 0) const; /** * Read data (text format) into the given stream. @@ -438,12 +439,13 @@ class AbstractFSNode * Read data (binary format) into the given buffer. * * @param buffer The buffer to contain the data (allocated in this method). + * @param size The amount of data to read (0 means read all data). * * @return The number of bytes read (0 in the case of failure) * This method can throw exceptions, and should be used inside * a try-catch block. */ - virtual size_t read(ByteBuffer& buffer) const { return 0; } + virtual size_t read(ByteBuffer& buffer, size_t size) const { return 0; } /** * Read data (text format) into the given stream. diff --git a/src/emucore/OSystem.cxx b/src/emucore/OSystem.cxx index 8f11211e0..4dbbbc653 100644 --- a/src/emucore/OSystem.cxx +++ b/src/emucore/OSystem.cxx @@ -44,6 +44,7 @@ #include "MD5.hxx" #include "Cart.hxx" #include "CartCreator.hxx" +#include "CartDetector.hxx" #include "FrameBuffer.hxx" #include "TIASurface.hxx" #include "TIAConstants.hxx" @@ -688,8 +689,16 @@ ByteBuffer OSystem::openROM(const FilesystemNode& rom, string& md5, size_t& size // but also adds a properties entry if the one for the ROM doesn't // contain a valid name + // First check if this is a 'streaming' ROM (one where we only read + // a portion of the file) + size_t sizeToRead = CartDetector::isProbablyMVC(rom); + + // Next check if rom is a valid size + // TODO: We should check if ROM is < Cart::maxSize(), but only + // if it's not a ZIP file (that size should be higher; still TBD) + ByteBuffer image; - if((size = rom.read(image)) == 0) + if((size = rom.read(image, sizeToRead)) == 0) return nullptr; // If we get to this point, we know we have a valid file to open diff --git a/src/emucore/Serializer.cxx b/src/emucore/Serializer.cxx index 1d45bc8d0..57657712a 100644 --- a/src/emucore/Serializer.cxx +++ b/src/emucore/Serializer.cxx @@ -94,11 +94,15 @@ void Serializer::rewind() } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -size_t Serializer::size() const +size_t Serializer::size() { - myStream->seekp(0, std::ios::end); + std::streampos oldPos = myStream->tellp(); - return myStream->tellp(); + myStream->seekp(0, std::ios::end); + size_t s = myStream->tellp(); + setPosition(oldPos); + + return s; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/emucore/Serializer.hxx b/src/emucore/Serializer.hxx index 6faac1910..5f0b28eb1 100644 --- a/src/emucore/Serializer.hxx +++ b/src/emucore/Serializer.hxx @@ -70,9 +70,9 @@ class Serializer void rewind(); /** - Returns the current write pointer location. + Returns the current total size of the stream. */ - size_t size() const; + size_t size(); /** Reads a byte value (unsigned 8-bit) from the current input stream. From cc6d53d5610445405886d9ee60aed019a14edce1 Mon Sep 17 00:00:00 2001 From: Stephen Anthony Date: Mon, 3 May 2021 20:59:35 -0230 Subject: [PATCH 12/17] Fix libretro build. --- src/emucore/CartMVC.cxx | 2 +- src/libretro/FSNodeLIBRETRO.cxx | 2 +- src/libretro/FSNodeLIBRETRO.hxx | 2 +- src/libretro/Makefile.common | 1 + 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/emucore/CartMVC.cxx b/src/emucore/CartMVC.cxx index 0562bca00..aac2a97fc 100644 --- a/src/emucore/CartMVC.cxx +++ b/src/emucore/CartMVC.cxx @@ -803,7 +803,7 @@ void MovieCart::updateTransport() if (temp == myDirectionValue) myInputs.updateDirection(temp); - myDirectionValue = temp; + myDirectionValue = temp; } else { diff --git a/src/libretro/FSNodeLIBRETRO.cxx b/src/libretro/FSNodeLIBRETRO.cxx index 12c377ed6..cb4d24011 100644 --- a/src/libretro/FSNodeLIBRETRO.cxx +++ b/src/libretro/FSNodeLIBRETRO.cxx @@ -92,7 +92,7 @@ AbstractFSNodePtr FilesystemNodeLIBRETRO::getParent() const } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -size_t FilesystemNodeLIBRETRO::read(ByteBuffer& image) const +size_t FilesystemNodeLIBRETRO::read(ByteBuffer& image, size_t) const { image = make_unique(Cartridge::maxSize()); diff --git a/src/libretro/FSNodeLIBRETRO.hxx b/src/libretro/FSNodeLIBRETRO.hxx index 5dd17d0d7..a7fcb211d 100644 --- a/src/libretro/FSNodeLIBRETRO.hxx +++ b/src/libretro/FSNodeLIBRETRO.hxx @@ -49,7 +49,7 @@ class FilesystemNodeLIBRETRO : public AbstractFSNode bool getChildren(AbstractFSList& list, ListMode mode) const override; AbstractFSNodePtr getParent() const override; - size_t read(ByteBuffer& image) const override; + size_t read(ByteBuffer& image, size_t) const override; protected: string _name; diff --git a/src/libretro/Makefile.common b/src/libretro/Makefile.common index dce248743..a0f099ed0 100644 --- a/src/libretro/Makefile.common +++ b/src/libretro/Makefile.common @@ -85,6 +85,7 @@ SOURCES_CXX := \ $(CORE_DIR)/emucore/CartFC.cxx \ $(CORE_DIR)/emucore/CartFE.cxx \ $(CORE_DIR)/emucore/CartMDM.cxx \ + $(CORE_DIR)/emucore/CartMVC.cxx \ $(CORE_DIR)/emucore/CartMNetwork.cxx \ $(CORE_DIR)/emucore/CartSB.cxx \ $(CORE_DIR)/emucore/CartTVBoy.cxx \ From c18034385ee01f7dead4772263850da1cfb5fc44 Mon Sep 17 00:00:00 2001 From: Lo Def Date: Sat, 5 Jun 2021 14:25:28 -0400 Subject: [PATCH 13/17] Remove partial top and bottom line for square area --- src/emucore/CartMVC.cxx | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/src/emucore/CartMVC.cxx b/src/emucore/CartMVC.cxx index aac2a97fc..11f61cd84 100644 --- a/src/emucore/CartMVC.cxx +++ b/src/emucore/CartMVC.cxx @@ -57,6 +57,28 @@ class StreamReader return bool(myFile); } + void blankPartialLines(bool index) { + constexpr int colorSize = 192 * 5; + if (index) + { + // top line + myColor[0] = 0; + myColor[1] = 0; + myColor[2] = 0; + myColor[3] = 0; + myColor[4] = 0; + } + else + { + // bottom line + myColor[colorSize - 5] = 0; + myColor[colorSize - 4] = 0; + myColor[colorSize - 3] = 0; + myColor[colorSize - 2] = 0; + myColor[colorSize - 1] = 0; + } + } + void swapField(bool index) { if(index) { @@ -129,9 +151,9 @@ class StreamReader const uInt8* myGraphOverride{nullptr}; const uInt8* myTimecode{nullptr}; - const uInt8* myColor{nullptr}; + uInt8* myColor{nullptr}; const uInt8* myVersion{nullptr}; - const uInt8* myFrame{nullptr}; + const uInt8* myFrame{nullptr}; uInt8 myBuffer1[CartridgeMVC::MVC_FIELD_SIZE]; uInt8 myBuffer2[CartridgeMVC::MVC_FIELD_SIZE]; @@ -1204,6 +1226,8 @@ void MovieCart::runStateMachine() fill_addr_end_lines(); myStream.swapField(myBufferIndex); + myStream.blankPartialLines(myOdd); + myBufferIndex = !myBufferIndex; updateTransport(); From 72f64dd84dac51d8b243d91dbfb996124f77b63d Mon Sep 17 00:00:00 2001 From: Stephen Anthony Date: Tue, 8 Jun 2021 20:48:12 -0230 Subject: [PATCH 14/17] First pass at state load/save for MVC scheme. --- src/emucore/CartMVC.cxx | 290 +++++++++++++++++++++++++++++++++------- 1 file changed, 242 insertions(+), 48 deletions(-) diff --git a/src/emucore/CartMVC.cxx b/src/emucore/CartMVC.cxx index 11f61cd84..34dfceece 100644 --- a/src/emucore/CartMVC.cxx +++ b/src/emucore/CartMVC.cxx @@ -16,6 +16,7 @@ //============================================================================ #include "Serializer.hxx" +#include "Serializable.hxx" #include "System.hxx" #include "CartMVC.hxx" @@ -44,7 +45,7 @@ /** Simulate retrieval 512 byte chunks from a serial source */ -class StreamReader +class StreamReader : public Serializable { public: StreamReader() = default; @@ -57,49 +58,39 @@ class StreamReader return bool(myFile); } - void blankPartialLines(bool index) { - constexpr int colorSize = 192 * 5; - if (index) - { - // top line - myColor[0] = 0; - myColor[1] = 0; - myColor[2] = 0; - myColor[3] = 0; - myColor[4] = 0; - } - else - { - // bottom line - myColor[colorSize - 5] = 0; - myColor[colorSize - 4] = 0; - myColor[colorSize - 3] = 0; - myColor[colorSize - 2] = 0; - myColor[colorSize - 1] = 0; - } - } - - void swapField(bool index) { - if(index) + void blankPartialLines(bool index) { + constexpr int colorSize = 192 * 5; + if (index) { - myVersion = myBuffer1 + VERSION_DATA_OFFSET; - myFrame = myBuffer1 + FRAME_DATA_OFFSET; - myAudio = myBuffer1 + AUDIO_DATA_OFFSET; - myGraph = myBuffer1 + GRAPH_DATA_OFFSET; - myTimecode= myBuffer1 + TIMECODE_DATA_OFFSET; - myColor = myBuffer1 + COLOR_DATA_OFFSET; + // top line + myColor[0] = 0; + myColor[1] = 0; + myColor[2] = 0; + myColor[3] = 0; + myColor[4] = 0; } else { - myVersion = myBuffer2 + VERSION_DATA_OFFSET; - myFrame = myBuffer2 + FRAME_DATA_OFFSET; - myAudio = myBuffer2 + AUDIO_DATA_OFFSET; - myGraph = myBuffer2 + GRAPH_DATA_OFFSET; - myTimecode = myBuffer2 + TIMECODE_DATA_OFFSET; - myColor = myBuffer2 + COLOR_DATA_OFFSET; + // bottom line + myColor[colorSize - 5] = 0; + myColor[colorSize - 4] = 0; + myColor[colorSize - 3] = 0; + myColor[colorSize - 2] = 0; + myColor[colorSize - 1] = 0; } } + void swapField(bool index) { + uInt8* offset = index ? myBuffer1 : myBuffer2; + + myVersion = offset + VERSION_DATA_OFFSET; + myFrame = offset + FRAME_DATA_OFFSET; + myAudio = offset + AUDIO_DATA_OFFSET; + myGraph = offset + GRAPH_DATA_OFFSET; + myTimecode = offset + TIMECODE_DATA_OFFSET; + myColor = offset + COLOR_DATA_OFFSET; + } + bool readField(uInt32 fnum, bool index) { if(myFile) { @@ -135,6 +126,54 @@ class StreamReader void startTimeCode() { myGraph = myTimecode; } + bool save(Serializer& out) const override { + try + { + out.putByteArray(myBuffer1, CartridgeMVC::MVC_FIELD_SIZE); + out.putByteArray(myBuffer2, CartridgeMVC::MVC_FIELD_SIZE); + + // FIXME - complete this + #if 0 + const uInt8* myAudio + const uInt8* myGraph + const uInt8* myGraphOverride + const uInt8* myTimecode + const uInt8* myColor + const uInt8* myVersion + const uInt8* myFrame + #endif + } + catch(...) + { + return false; + } + return true; + } + + bool load(Serializer& in) override { + try + { + in.getByteArray(myBuffer1, CartridgeMVC::MVC_FIELD_SIZE); + in.getByteArray(myBuffer2, CartridgeMVC::MVC_FIELD_SIZE); + + // FIXME - complete this + #if 0 + const uInt8* myAudio + const uInt8* myGraph + const uInt8* myGraphOverride + const uInt8* myTimecode + const uInt8* myColor + const uInt8* myVersion + const uInt8* myFrame + #endif + } + catch(...) + { + return false; + } + return true; + } + private: static constexpr int VERSION_DATA_OFFSET = 0, @@ -151,9 +190,9 @@ class StreamReader const uInt8* myGraphOverride{nullptr}; const uInt8* myTimecode{nullptr}; - uInt8* myColor{nullptr}; + uInt8* myColor{nullptr}; const uInt8* myVersion{nullptr}; - const uInt8* myFrame{nullptr}; + const uInt8* myFrame{nullptr}; uInt8 myBuffer1[CartridgeMVC::MVC_FIELD_SIZE]; uInt8 myBuffer2[CartridgeMVC::MVC_FIELD_SIZE]; @@ -166,7 +205,7 @@ class StreamReader /** State of current switches and joystick positions to control MovieCart */ -class MovieInputs +class MovieInputs : public Serializable { public: MovieInputs() = default; @@ -193,6 +232,36 @@ class MovieInputs reset = val & TRANSPORT_RESET; } + bool save(Serializer& out) const override { + try + { + out.putBool(bw); out.putBool(fire); + out.putBool(select); out.putBool(reset); + out.putBool(right); out.putBool(left); + out.putBool(up); out.putBool(down); + } + catch(...) + { + return false; + } + return true; + } + + bool load(Serializer& in) override { + try + { + bw = in.getBool(); fire = in.getBool(); + select = in.getBool(); reset = in.getBool(); + right = in.getBool(); left = in.getBool(); + up = in.getBool(); down = in.getBool(); + } + catch(...) + { + return false; + } + return true; + } + private: static constexpr uInt8 TRANSPORT_RIGHT = 0x10, @@ -651,7 +720,7 @@ static constexpr uInt8 levelBarsOddData[] = { }; //////////////////////////////////////////////////////////////////////////////// -class MovieCart +class MovieCart : public Serializable { public: MovieCart() = default; @@ -659,6 +728,9 @@ class MovieCart bool init(const string& path); bool process(uInt16 address); + bool save(Serializer& out) const override; + bool load(Serializer& in) override; + uInt8 readROM(uInt16 address) const { return myROM[address & 1023]; } @@ -668,7 +740,7 @@ class MovieCart } private: - enum Mode + enum Mode : uInt8 { Volume, Bright, @@ -708,8 +780,6 @@ class MovieCart void updateTransport(); - StreamReader myStream; - // data uInt8 myROM[1024]; @@ -739,6 +809,7 @@ class MovieCart uInt8 myDrawLevelBars{0}; uInt8 myDrawTimeCode{0}; + StreamReader myStream; MovieInputs myInputs; MovieInputs myLastInputs; @@ -1022,7 +1093,6 @@ void MovieCart::fill_addr_right_line() writeColor(addr_set_gcol7 + 1); writeColor(addr_set_gcol8 + 1); writeColor(addr_set_gcol9 + 1); - } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1226,7 +1296,7 @@ void MovieCart::runStateMachine() fill_addr_end_lines(); myStream.swapField(myBufferIndex); - myStream.blankPartialLines(myOdd); + myStream.blankPartialLines(myOdd); myBufferIndex = !myBufferIndex; updateTransport(); @@ -1301,6 +1371,112 @@ bool MovieCart::process(uInt16 address) return a12; } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool MovieCart::save(Serializer& out) const +{ + try + { + out.putByteArray(myROM, 1024); + + // title screen state + out.putInt(myTitleCycles); + out.putInt(static_cast(myTitleState)); + + // address info + out.putBool(myA7); + out.putBool(myA10); + out.putByte(myA10_Count); + + // state machine info + out.putByte(myState); + out.putBool(myPlaying); + out.putBool(myOdd); + out.putBool(myBufferIndex); + + out.putByte(myLines); + out.putInt(myFrameNumber); + + out.putByte(myMode); + out.putByte(myBright); + out.putByte(myForceColor); + + // expressed in frames + out.putByte(myDrawLevelBars); + out.putByte(myDrawTimeCode); + + if(!myStream.save(out)) throw; + if(!myInputs.save(out)) throw; + if(!myLastInputs.save(out)) throw; + + out.putByte(mySpeed); + out.putByte(myJoyRepeat); + out.putByte(myDirectionValue); + out.putByte(myButtonsValue); + + out.putByte(myVolume); +// FIXME const uInt8* myVolumeScale{scales[DEFAULT_LEVEL]}; + out.putByte(myFirstAudioVal); + } + catch(...) + { + return false; + } + return true; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool MovieCart::load(Serializer& in) +{ + try + { + in.getByteArray(myROM, 1024); + + // title screen state + myTitleCycles = in.getInt(); + myTitleState = static_cast(in.getInt()); + + // address info + myA7 = in.getBool(); + myA10 = in.getBool(); + myA10_Count = in.getByte(); + + // state machine info + myState = in.getByte(); + myPlaying = in.getBool(); + myOdd = in.getBool(); + myBufferIndex = in.getBool(); + + myLines = in.getByte(); + myFrameNumber = in.getInt(); + + myMode = in.getByte(); + myBright = in.getByte(); + myForceColor = in.getByte(); + + // expressed in frames + myDrawLevelBars = in.getByte(); + myDrawTimeCode = in.getByte(); + + if(!myStream.load(in)) throw; + if(!myInputs.load(in)) throw; + if(!myLastInputs.load(in)) throw; + + mySpeed = in.getByte(); + myJoyRepeat = in.getByte(); + myDirectionValue = in.getByte(); + myButtonsValue = in.getByte(); + + myVolume = in.getByte(); +// FIXME const uInt8* myVolumeScale{scales[DEFAULT_LEVEL]}; + myFirstAudioVal = in.getByte(); + } + catch(...) + { + return false; + } + return true; +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CartridgeMVC::CartridgeMVC(const string& path, size_t size, const string& md5, const Settings& settings, @@ -1368,11 +1544,29 @@ bool CartridgeMVC::poke(uInt16 address, uInt8 value) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool CartridgeMVC::save(Serializer& out) const { - return false; // TODO: implement this + try + { + if(!myMovie->save(out)) throw; + } + catch(...) + { + return false; + } + + return true; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool CartridgeMVC::load(Serializer& in) { - return false; // TODO: implement this + try + { + if(!myMovie->load(in)) throw; + } + catch(...) + { + return false; + } + + return true; } From 4578be499d1594c7b950926b7b76dad1c60d60f0 Mon Sep 17 00:00:00 2001 From: Lo Def Date: Fri, 11 Jun 2021 01:01:51 -0400 Subject: [PATCH 15/17] Keep vblank lines consistently at 36 each field. --- src/emucore/CartMVC.cxx | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) mode change 100644 => 100755 src/emucore/CartMVC.cxx diff --git a/src/emucore/CartMVC.cxx b/src/emucore/CartMVC.cxx old mode 100644 new mode 100755 index 34dfceece..7641602af --- a/src/emucore/CartMVC.cxx +++ b/src/emucore/CartMVC.cxx @@ -324,12 +324,13 @@ class MovieInputs : public Serializable #define addr_set_aud_endlines 0xa8c #define addr_set_overscan_size 0xa90 #define addr_set_vblank_size 0xaa6 -#define addr_pick_transport 0xaaf -#define addr_transport_direction 0xab2 -#define addr_transport_buttons 0xabb -// #define addr_transport_done 0xac4 -// #define addr_wait_lines 0xac9 -// #define addr_transport_done1 0xada +#define addr_pick_extra_lines 0xaaf +#define addr_pick_transport 0xab6 +#define addr_transport_direction 0xab9 +#define addr_transport_buttons 0xac2 +// #define addr_transport_done 0xacb +// #define addr_wait_lines 0xad0 +// #define addr_transport_done1 0xae1 // #define addr_draw_title 0xb00 #define addr_title_loop 0xb50 // #define addr_black_bar 0xb52 @@ -427,12 +428,12 @@ static constexpr unsigned char kernelROM[] = { 6, 133, 4, 169, 2, 133, 5, 169, 1, 133, 38, 169, 0, 133, 32, 169, 240, 133, 33, 133, 42, 162, 5, 202, 208, 253, 133, 43, 76, 128, 250, 255, 160, 0, 132, 27, 132, 28, 132, 27, 169, 0, 169, 0, 169, 0, 133, 25, - 162, 29, 32, 201, 250, 169, 2, 133, 0, 162, 3, 32, 201, 250, 169, 0, - 133, 0, 169, 2, 133, 1, 162, 37, 32, 201, 250, 162, 0, 134, 1, 76, - 187, 250, 173, 128, 2, 74, 74, 74, 76, 196, 250, 165, 12, 10, 173, 130, - 2, 42, 41, 23, 133, 129, 76, 70, 249, 133, 2, 169, 0, 177, 130, 133, - 25, 165, 129, 240, 5, 198, 129, 173, 128, 20, 200, 202, 208, 235, 96, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 162, 29, 32, 208, 250, 169, 2, 133, 0, 162, 3, 32, 208, 250, 169, 0, + 133, 0, 169, 2, 133, 1, 162, 37, 32, 208, 250, 162, 0, 134, 1, 162, + 0, 240, 3, 32, 208, 250, 76, 194, 250, 173, 128, 2, 74, 74, 74, 76, + 203, 250, 165, 12, 10, 173, 130, 2, 42, 41, 23, 133, 129, 76, 70, 249, + 133, 2, 169, 0, 177, 130, 133, 25, 165, 129, 240, 5, 198, 129, 173, 128, + 20, 200, 202, 208, 235, 96, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 162, 30, 32, 82, 251, 169, 2, 133, 0, 162, 3, 32, 82, 251, 169, 0, 133, 0, 169, 2, 133, 1, 162, 37, 32, 82, 251, 169, 0, 133, 1, 198, @@ -1135,17 +1136,23 @@ void MovieCart::fill_addr_end_lines() if(!myOdd) myFirstAudioVal = myStream.readAudio(); - // normally overscan=30, vblank=37 - // todo: clicky noise.. + // keep at overscan=29, vblank=36 + // or overscan=30, vblank=36 + 1 blank line + if(myOdd) { writeROM(addr_set_overscan_size + 1, 29); writeROM(addr_set_vblank_size + 1, 36); + + writeROM(addr_pick_extra_lines + 1, 0); } else { writeROM(addr_set_overscan_size + 1, 30); - writeROM(addr_set_vblank_size + 1, 37); + writeROM(addr_set_vblank_size + 1, 36); + + // extra line after vblank + writeROM(addr_pick_extra_lines + 1, 1); } if(!myBufferIndex) From 61f5b1aa2a77306cb35d93de43b2a984ccc3119a Mon Sep 17 00:00:00 2001 From: Lo Def Date: Fri, 11 Jun 2021 01:02:08 -0400 Subject: [PATCH 16/17] Fixed stepping forward faster than stepping back --- src/emucore/CartMVC.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/emucore/CartMVC.cxx b/src/emucore/CartMVC.cxx index 7641602af..54c509396 100755 --- a/src/emucore/CartMVC.cxx +++ b/src/emucore/CartMVC.cxx @@ -1042,7 +1042,7 @@ void MovieCart::updateTransport() if(myMode == Mode::Time) { if(myInputs.right && !myLastInputs.right) - step = 3; + step = 1; else if(myInputs.left && !myLastInputs.left) step = -3; else From 0b63decafc28260cc8bb85adeefc81239793a1c6 Mon Sep 17 00:00:00 2001 From: Stephen Anthony Date: Sat, 28 Aug 2021 17:16:45 -0230 Subject: [PATCH 17/17] Added preliminary support for 'MVC' bankswitching scheme by Rob Bairos. --- Changes.txt | 3 +++ src/emucore/CartMVC.cxx | 12 ++++++------ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/Changes.txt b/Changes.txt index b79a29346..07b70ecf6 100644 --- a/Changes.txt +++ b/Changes.txt @@ -14,6 +14,9 @@ 6.5.3 to 6.6 (??? ??, 202?) + * Added preliminary support for 'MVC' bankswitching scheme by + Rob Bairos. + * Added web links for many games * Debugger: added optional logging of breaks and traps diff --git a/src/emucore/CartMVC.cxx b/src/emucore/CartMVC.cxx index 54c509396..37d3d6024 100755 --- a/src/emucore/CartMVC.cxx +++ b/src/emucore/CartMVC.cxx @@ -132,8 +132,7 @@ class StreamReader : public Serializable out.putByteArray(myBuffer1, CartridgeMVC::MVC_FIELD_SIZE); out.putByteArray(myBuffer2, CartridgeMVC::MVC_FIELD_SIZE); - // FIXME - complete this - #if 0 + #if 0 // FIXME - determine whether we need to load/save this const uInt8* myAudio const uInt8* myGraph const uInt8* myGraphOverride @@ -156,8 +155,7 @@ class StreamReader : public Serializable in.getByteArray(myBuffer1, CartridgeMVC::MVC_FIELD_SIZE); in.getByteArray(myBuffer2, CartridgeMVC::MVC_FIELD_SIZE); - // FIXME - complete this - #if 0 + #if 0 // FIXME - determine whether we need to load/save this const uInt8* myAudio const uInt8* myGraph const uInt8* myGraphOverride @@ -1421,7 +1419,8 @@ bool MovieCart::save(Serializer& out) const out.putByte(myButtonsValue); out.putByte(myVolume); -// FIXME const uInt8* myVolumeScale{scales[DEFAULT_LEVEL]}; + // FIXME - determine whether we need to load/save this + // const uInt8* myVolumeScale{scales[DEFAULT_LEVEL]}; out.putByte(myFirstAudioVal); } catch(...) @@ -1474,7 +1473,8 @@ bool MovieCart::load(Serializer& in) myButtonsValue = in.getByte(); myVolume = in.getByte(); -// FIXME const uInt8* myVolumeScale{scales[DEFAULT_LEVEL]}; + // FIXME - determine whether we need to load/save this + // const uInt8* myVolumeScale{scales[DEFAULT_LEVEL]}; myFirstAudioVal = in.getByte(); } catch(...)