 ==============================================================================
 PlusBlaster
 Version 0.1.0.0 (October 3, 2026)
 ==============================================================================
 Copyright (C) 2026 Osman Celimli, PenguiNet
 http://www.tailchao.com/

                               { W A R N I N G }

     INSTALLING THIS FIRMWARE WILL RENDER YOUR 7800+ CONSOLE UNABLE TO PLAY
       GAME SOFTWARE AS INTENDED, AND REPURPOSE IT AS A DEVELOPMENT TOOL.

                   IF THIS ISN'T WHAT YOU WANT THEN STOP NOW.


 ------------------------------------------------------------------------------
 Table of Contents
 ------------------------------------------------------------------------------

 1) Introduction
    1.1) What is PlusBlaster?
    1.2) Features
    1.3) Device Support

 2) License

 3) What's Included

 4) Getting Started
    4.1) Gather Ingredients
    4.2) Modify the 7800+
    4.3) Install the MG32 Firmware
    4.4) Interface with BupShell

 5) Using BupShell
    5.1) Syntax
    5.2) Basic Commands
    5.3) PlusBlaster Extensions

 6) Checking and Extracting Data
    6.1) Media Detection
    6.2) Content Archival

 7) Programming
    7.1) Single Device Mode
    7.2) Factory Mode

 8) Low Level Cartridge Interface
    8.1) Introduction
    8.2) Opening and Closing
    8.3) Set Parking Address
    8.4) Read
    8.5) Read Array
    8.6) Pull
    8.7) Write
    8.8) Maria Fetch
    8.9) Maria Fetch Array

 9) Reference Materials


 ------------------------------------------------------------------------------
 1) Introduction
 ------------------------------------------------------------------------------

 1.1) What is PlusBlaster?

      PlusBlaster is an alternative firmware for the Atari 7800+'s cartridge
      interface which allows it to be used as a production, archival, and
      reverse engineering tool.


 1.2) Features

      * Archive Data from VCS and ProSystem Cartridges
      * Write to Programmable Cartridges
      * Directly Control the Cartridge Interface


 1.3) Device Support

      1.3.1) Detection and Archival

             * 2K, 4K, F8, F6, FA, DPC, FE, E0, E7
             * 16K, 32K, 48K, SUPER, ACTIVISION, ABSOLUTE, SOUPER, BANKSET


      1.3.2) Programming

             * PenguiNet FoxBoard with SST39SF0x0 NOR Flash (x == 1,2,4)


 ------------------------------------------------------------------------------
 2) License
 ------------------------------------------------------------------------------

 This software is provided 'as-is', without any express or implied warranty.
 In no event will the authors be held liable for any damages arising from the
 use of this software.


 ------------------------------------------------------------------------------
 3) What's Included
 ------------------------------------------------------------------------------

 .\MG32.bin     - PlusBlaster firmware for the Megawin MG32F02U128
 .\MG32MEGA.bin - PlusBlaster Megabit Edition (J5 UART @ 1000000bps, 8N1)

 .\README.txt   - What you're perusing right now


 ------------------------------------------------------------------------------
 4) Getting Started
 ------------------------------------------------------------------------------

 4.1) Gather Ingredients

      [ ] Atari 7800+ Console

      As far as I know, these are all identical. The one I reverse engineered
      had "PCB09-150924" and "2024-6-26A" stamped on its cartridge reader.

      [ ] Megawin M-Link
      [ ] Megawin OCD32 Software Package

      https://www.megawin.com.tw/
      https://www.megawin.com.tw/product/MG32F02U128

      [ ] Terminal Emulation Software with XMODEM File Transfer Support
      [ ] USB to UART @ 5V Bridge
      [ ] Male Breakaway Headers (2.54mm)
      [ ] Female to Female Jumpers (2.54mm)

      You might already have all of these available if you're up to any other
      electronic mischief. My personal choice for the first two are Tera Term
      paired with a DSD TECH SH-U09C5.


 4.2) Modify the 7800+

      4.2.1) Remove all five screws from the unit's base, then carefully lift
             its lid to reveal the electronics inside. Disconnect "LED1" from
             the controller board to completely free the lid.

      4.2.2) Remove the RK-3128, which is the black board with a heatsink and
             HDMI port in the rear of the case. This'll require disconnecting
             J6 from the cartridge reader and removing four more screws. Once
             it's free, put the board aside. You'll no longer need it.

      4.2.3) Temporarily remove the cartridge reader, then solder male headers
             in J3, J5, and J8. Reinstall the board once you're done.

      4.2.4) Use female to female headers to connect both the UART Bridge (J5)
             and M-Link (J8). Note the former's legend is written from the
             microcontroller's perspective, so "TX" is outgoing.

      4.2.5) If possible, replace the lid. You're ready to go!


 4.3) Install the MG32 Firmware

      4.3.1) Connect the M-Link to your workstation.

      4.3.2) Run ICP32_Programmer.exe, which is packaged with Megawin's OCD32.

      4.3.3) Ensure it's configured as shown below...

             MCU Type    [Cortex-M0]
             MCU Series  [MG32F02 Series]
             MCU Part No [MG32F02U128   ]

             Hardware Option Setting
             ISP-memory           IAP-memory           [ ] LOCK    [ ] PC_IOM
             [0.0k             ]  [0.0k             ]  [ ] BOD0_WE
             BOOT_MS              IWDT_DIV             [ ] BOD1_WE
             [Application Flash]  [F/4096           ]  [ ] IWDT_EN
             BOD1_Level                                [ ] IWDT_WP
             [Detect 4.2V      ]                       [ ] IWDT_WE
                                                       [ ] IWDT_SLP
                                                       [ ] IWDT_STP

      4.3.4) Click [Load File(L)] and select MG32.bin, which is included with
             this PlusBlaster firmware distribution. You should then receive
             a "Select Insert Area" prompt, fill it out like this...

             (*) AP (Code)
             ( ) IAP (Data)
                 Address : 0x [ 0001EC00 ]

             [*] Clear code buffer
             [ ] Fill unused bytes(I)
                 ( ) 00       (*) FF

             ...then click [OK].

      4.3.5) Hold the 7800+'s [POWER] button, and click [Update Target(U)] to
             flash the MCU. You must hold the [POWER] button down for the
             entire update cycle, or the unit will switch off early.

      4.3.6) You'll get a dialog confirming a successful update if everything
             went well. If not, check your wiring and try again.


 4.4) Interface with BupShell

      4.4.1) Connect the UART Bridge to your workstation.

      4.4.2) Open your terminal emulator of choice then connect to the bridge
             at 115200bps, 8N1, no flow control. Use a rate of 1000000bps if
             you've installed the Megabit Edition firmware.

      4.4.3) Power cycle the 7800+, you should be greeted by the following...

             Welcome to BupShell!
             Built on Oct  3 2026 07:38:40

             ]_

      4.4.4) Congratulations, you've completed your PlusBlaster installation!


 ------------------------------------------------------------------------------
 5) Using BupShell
 ------------------------------------------------------------------------------

 5.1) Syntax

      Using a DEC VT-100 compatible terminal is recommended, as BupShell uses
      its features for both interaction and display. The majority of commands
      are case insensitive, submitted as only one per line, and terminated by
      a carriage return or line feed.

      Numeric values can be entered in decimal (default), hexadecimal (with a
      prefix of '$' or '0x'), or binary (with a prefix of '%' or '0b').

      The arrow keys may be used to edit the current line (left and right) or
      navigate a short command history (up and down).


 5.2) Basic Commands

      5.2.1) cls
             Clears the screen.

      5.2.2) help [command]
             Provides help for BupShell commands.

      5.2.3) peek address [length]
             Reveals the contents of memory. Keep in mind this is internal to
             the microcontroller, and doesn't involve the cartridge.

      5.2.4) exit
             Closes BupShell, this will also power off the console.


 5.3) PlusBlaster Extensions

      5.3.1) pwr {auto|hold|off}
             Interacts with the power management library.

             {auto} switches to the default mode, where the [POWER] button is
             allowed to shut down the console when pressed.

             {hold} disables the [POWER] button's functionality.

             {off} immediately switches off the console.


 ------------------------------------------------------------------------------
 6) Checking and Extracting Data
 ------------------------------------------------------------------------------

 6.1) Media Detection
      crd check

      Use "crd check" to examine a cartridge and attempt to detect its target
      platform, mapper family, implemented options, and media capacity.

      Note that the PlusBlaster will not be able to detect certain write only
      features such as expansion sound chips with no visible registers.


 6.2) Content Archival
      crd extract

      Use "crd extract" to read the contents of a cartridge and then transfer
      them to your workstation over XMODEM. Any sections of memory which have
      distinct purposes, such as a cartridge with both ROM and NVRAM, will be
      split into separate transfers.

      Data are typically linear, and the individual pages of any bankswitched
      cartridges are arranged and transferred sequentially whenever possible.

      However, there are a few special cases...


      F8SC, F6SC, F4SC (F8/6/4 + SARA)

      The RAM hole at $1000 - $10FF is converted into padding at the start of
      each page, rounding their length to 4KB.

      002000  __________
      001FFF |          |
             |          |
             |  PAGE 1  |
             |          |
      001100 |          |
      001000 |FFFFFFFFFF|
      000FFF |          |
             |          |
             |  PAGE 0  |
             |          |
      000100 |          |
      000000 |FFFFFFFFFF|


      FA

      The RAM hole at $1000 - $11FF is converted into padding at the start of
      each page, rounding their length to 4KB.

      003000  __________
      002FFF |          |
             |          |
             |  PAGE 2  |
             |          |
      002200 |          |
      002000 |FFFFFFFFFF|
      001FFF |          |
             |          |
             |  PAGE 1  |
             |          |
      001200 |          |
      001000 |FFFFFFFFFF|
      000FFF |          |
             |          |
             |  PAGE 0  |
             |          |
      000200 |          |
      000000 |FFFFFFFFFF|


      DPC

      The register block at $1000 - $107F and $1800 - $187F is converted into
      padding at the start and middle of each page, rounding their length (as
      usual) to 4KB.

      002000  __________
      001FFF |          |
             |  PAGE 1  |
             | UPPER 2K |
      001880 |          |
      001800 |FFFFFFFFFF|
             |          |
             |  PAGE 1  |
             | LOWER 2K |
      001080 |          |
      001000 |FFFFFFFFFF|
      000FFF |          |
             |  PAGE 0  |
             | UPPER 2K |
      000880 |          |
      000800 |FFFFFFFFFF|
             |          |
             |  PAGE 0  |
             | LOWER 2K |
      000080 |          |
      000000 |FFFFFFFFFF|


      E7

      The RAM hole at $1800 - $19FF is converted into padding which is placed
      between the last selectable page and before the fixed region's data.

      004000  __________
      003FFF |          |
             | FIX DATA |
             |  REGION  |
      003A00 |          |
      003800 |FFFFFFFFFF|
      0037FF |          |
             |          |
             |  PAGE 6  |
             |          |
      003000 |__________|
      002FFF |          |
             |          |
             -   ....   -
             |          |
      001000 |__________|
      000FFF |          |
             |          |
             |  PAGE 1  |
             |          |
      000800 |__________|
      0007FF |          |
             |          |
             |  PAGE 0  |
             |          |
      000000 |__________|


      ABSOLUTE

      Binaries are arranged as software indexes its pages, which is using two
      fixed values of '1' or '2' in that order. This is to keep compatibility
      with how most emulators expect the data to be formatted.

      010000  __________
      00FFFF |          | \
             |          |  \
             | FIX DATA |   \ Fixed region mapped to $8000 - $FFFF in
             |  REGION  |   / both Sally and Maria's view of memory.
             |          |  /
      008000 |__________| /
      007FFF |          | \
             | PAGE '2' |  \
      004000 |__________|   \ Selectable 16KB pages, where '1' or '2' is the
      003FFF |          |   / write value used to map one in $4000 - $7FFF.
             | PAGE '1' |  /
      000000 |__________| /


      BANKSET

      Binaries are divided into two halves with Sally's data in the first and
      then followed by Maria's in the second.

      LENGTH  __________
             |          |
             | MARIA'S  |
             |  SECTION |
       HALF  |__________|
      LENGTH |          |
             | SALLY'S  |
             |  SECTION |
      000000 |__________|


 ------------------------------------------------------------------------------
 7) Programming
 ------------------------------------------------------------------------------

 7.1) Single Device Mode
      cwr {foxboard} [erase]

      Data may be written to an edge programmable cartridge by using "cwr" in
      its single device mode, formatted as "cwr {board} [erase]".

      A list of supported {board}s is below...

      foxboard : PenguiNet FoxBoard with SST39SF0x0 NOR Flash (x == 1,2,4)

      Upon detection of a valid board, the PlusBlaster will scan its contents
      to ensure any writable memory is empty. If any suspect data are located
      then the operation will be canceled. Adding the [erase] argument will
      instead wipe the board and move on to the programming phase.

      New data may the sent to the PlusBlaster via XMODEM, and you'll receive
      a prompt detailing the expected payload types and sizes.


 7.2) Factory Mode

      COMING SOON!


 ------------------------------------------------------------------------------
 8) Low Level Cartridge Interface
 ------------------------------------------------------------------------------

 8.1) Introduction
      cio {o|c|i|r|ra|p|w|m|ma} [a] [d|l]

      The "cio" command grants you direct access to the cartridge interface's
      underlying read and write transactions. This can be used to diagnose
      issues with a particularly stubborn game, or reverse engineer a new
      species of cartridge hardware.

      Please note this feature is intended for the advanced user, and must be
      used with great caution and care. Writing to any region of memory where
      a ROM is unconditionally enabled will cause a bus fight, and may damage
      both the 7800+ and your cartridge.

      You have been warned.


 8.2) Opening and Closing
      cio o
      cio c

      You'll need to {o}pen the interface using "cio o" before performing any
      read or write transactions. This powers up the cartridge and places the
      bus in an idle state at address zero (or the parking address when it's
      enabled, see section 8.3 below).

      Similarly, you should always {c}lose the interface with "cio c" prior
      to removing a cartridge or using other media commands such as "crd"
      and "cwr".


 8.3) Set Parking Address
      cio i [a]

      After a write transaction completes, all the data lines are released to
      prevent drawing out an accidental bus fight. However, the address lines
      are held at their last state. This behavior may lead to data corruption
      in VCS cartridges, which typically accept writes using an address match.

      This can be bodged by using a "Parking Address", or setting the address
      lines to a safe location after completing any read or write. Parking is
      disabled by default, but you can enable it with "cio i [a]".

      For example, entering "cio i $80" would set the parking address to $80,
      a quiet spot in the VCS's zero page.

      You can disable parking again with "cio i".


 8.4) Read
      cio r [a]

      Read one byte of data from the given [a]ddress.


 8.5) Read Array
      cio ra [a] [l]

      Read a specified [l]ength of data, starting from the given [a]ddress.


 8.6) Pull
      cio p [a] [d]

      Perform a weak [d]ata write at the specified [a]ddress. This drives the
      data lines less aggressively than "cio w" and is intended for sussing
      out whether a region of memory is actually writable.

      For example...

      ]cio p $8000 $FF
      WP @ $8000 ~ FF : 55

      ...tries pulling the data lines high while writing to $8000, but senses
      they're being held at $55, hinting a read only device could be assigned
      to this address.

      Using test writes which are either all highs, or match a value which is
      consistently read from that memory location are recommended. The former
      is particularly important, as the microcontroller will use its internal
      pull up resistors any time a weak one is written with "cio p".


 8.7) Write
      cio w [a] [d]

      Write one byte of [d]ata to a given [a]ddress.


 8.8) Maria Fetch
      cio m [a]

      Read one byte of data as Maria.


 8.9) Maria Fetch Array
      cio ma [a] [l]

      Read a specified length of data as Maria.


 ------------------------------------------------------------------------------
 9) Reference Materials
 ------------------------------------------------------------------------------

 PCB09-150924
 MEGAWIN MG32F02U128

                       6 6 6 6 6 5 5 5 5 5 5 5 5 5 5 4
                       4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9
                       | | | | | | | | | | | | | | | |
                      ---------------------------------
                     /                                 \
                1 --| O                                 |-- 48
                2 --|                                   |-- 47
                3 --|                                   |-- 46
                4 --|                                   |-- 45
                5 --|                                   |-- 44
                6 --|                                   |-- 43
                7 --|                                   |-- 42
                8 --|                                   |-- 41
                9 --|                                   |-- 40
               10 --|                                   |-- 39
               11 --|                                   |-- 38
               12 --|                                   |-- 37
               13 --|                                   |-- 36
               14 --|                                   |-- 35
               15 --|                                   |-- 34
               16 --|                                   |-- 33
                     \                                 /
                      ---------------------------------
                       | | | | | | | | | | | | | | | |
                       1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 3
                       7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2
 
   1 PA7         1U | 17 PB7         A7 | 33 PC7         D4 | 49 PD7    BLINKY
   2 PA8         1D | 18 PB8         A8 | 34 PC8      J5/TX | 50 PD8 CARD_TEST
   3 PA9         1L | 19 PB9         A9 | 35 PC9      J5/RX | 51 PD9  /GAME_ON
   4 PA10        1R | 20 PB10       A10 | 36 PC10     J3/TX | 52 PD10
   5 PA11      1KEY | 21 PB11       A11 | 37 PC11     J3/RX | 53 PD11  PLUS_ON
   6 PA12      1AD1 | 22 PB12       A12 | 38 PC12        D5 | 54 VSS
   7 PA13      1AD2 | 23 PB13       A13 | 39 PC13        D6 | 55 VR0
   8 PA14    SELECT | 24 PB14       A14 | 40 PC14        D7 | 56 VDD
   9 PA15    /POWER | 25 PB15       A15 | 41 VSS1           | 57 VREF+
  10 PB0         A0 | 26 PC0         D0 | 42 PD0        R/W | 58 PA0      2AD2
  11 PB1         A1 | 27 PC1         D1 | 43 PD1       PHI2 | 59 PA1      2AD1
  12 PB2         A2 | 28 PC2         D2 | 44 PD2      /HALT | 60 PA2      2KEY
  13 PB3         A3 | 29 PC3         D3 | 45 PD3       /IRQ | 61 PA3        2R
  14 PB4         A4 | 30 PC4      SWCLK | 46 DM      USB/D- | 62 PA4        2L
  15 PB5         A5 | 31 PC5      SWDIO | 47 DP      USB/D+ | 63 PA5        2D
  16 PB6         A6 | 32 PC6     /RESET | 48 V33            | 64 PA6        2U

 IHRCO @ 12.0MHz or 11.0592MHz, based upon CSC_CR0_ST_SEL.
 ILRCO @ 32kHz.

 The PLUS_ON (PD11) signal controls the system's soft power switch. Driving it
 HIGH keeps the supply on, and driving it LOW (or not at all) switches it off.

 This same soft power circuit also is forced on whenever the [POWER] button is
 pressed and held, which is why you must hold [POWER] while flashing the MG32.

 Configure /POWER (PA15) as a digital input with its internal pullup resistor
 enabled, it'll then lower whenever the [POWER] button is pressed.


            J3 to RK-3128     | J5                | J8 to M-Link
           -------------------|-------------------|-------------------
            5V                | 5V                | CLK           PC4
            TX           PC10 | TX            PC8 | 5V
            RX           PC11 | RX            PC9 | DIO           PC5
            GND               | GND               | GND
                                                  | RST           PC6

            J1                | J4                | J6 to RK-3128
           -------------------|-------------------|-------------------
             1 R/W        PD0 |  1 1AD2      PA13 |  1 +5V
             2 /HALT      PD2 |  2 1AD1      PA12 |  2 +5V
             3 D3         PC3 |  3 1KEY      PA11 |  3 GND
             4 D4         PC7 |  4 1R        PA10 |  4 GND
             5 D5        PC12 |  5 1L         PA9 |  5 2PA/B
             6 D6        PC13 |  6 1D         PA8 |  6 SELECT    PA14
             7 D7        PC14 |  7 1U         PA7 |  7 RESET
             8 A12       PB12 |  8 2U         PA6 |  8 CARD_TEST  PD8
             9 A10       PB10 |  9 2D         PA5 |  9 RESET
            10 A11       PB11 | 10 2L         PA4 | 10 RX        PC10
            11 A9         PB9 | 11 2R         PA3 | 11 TX        PC11
            12 A8         PB8 | 12 2KEY       PA2 | 12 D-
            13 +5V *          | 13 2AD1       PA1 | 13 D+
            14 GND            | 14 2AD2       PA0 | 14 D-1
            15 A13       PB13 | 15 SELECT    PA14 | 15 D+1
            16 A14       PB14 | 16 RESET          | 16 1PA/B
            17 A15       PB15 | 17 POWER          | 17 PAUSE
            18 EAUD **        | 18 PAUSE          | 18 AUDIO_TEST
            19 A7         PB7 | 19 2PA/B          |
            20 A6         PB6 | 20 1PA/B          |
            21 A5         PB5 | 21 GND            |
            22 A4         PB4 | 22 GND            |
            23 A3         PB3 | 23 +5V            |
            24 A2         PB2 | 24 +5V            |
            25 A1         PB1 |
            26 A0         PB0 |
            27 D0         PC0 |
            28 D1         PC1 |
            29 D2         PC2 |
            30 GND            |
            31 /IRQ       PD3 |
            32 PHI2       PD1 |

 * Cartridge power is enabled by driving /GAME_ON low.
** EAUD is connected to AUDIO_TEST, which runs to the RK-3128's board.
