From 83ef56b39f4ca09dd89dbd60be85e7576eccf615 Mon Sep 17 00:00:00 2001 From: wwarthen Date: Fri, 30 May 2025 20:49:05 +0000 Subject: [PATCH] deploy: 81278afefed5ef3ca1fecf74a68da9e8c290b791 --- .nojekyll | 0 404.html | 189 + Applications/index.html | 3750 +++++++++ Catalog/index.html | 3986 +++++++++ Hardware/index.html | 4575 ++++++++++ Introduction/index.html | 691 ++ SystemGuide/Graphics/BankSwitchedMemory.svg | 366 + .../CharacterEmulationVideoServices.svg | 830 ++ SystemGuide/Graphics/Logo.svg | 62 + SystemGuide/Graphics/Panel.svg | 369 + SystemGuide/Graphics/hd1k.svg | 1088 +++ SystemGuide/Graphics/hd512.svg | 236 + SystemGuide/index.html | 7362 +++++++++++++++++ UserGuide/Graphics/BankSwitchedMemory.svg | 366 + .../CharacterEmulationVideoServices.svg | 830 ++ UserGuide/Graphics/Logo.svg | 62 + UserGuide/Graphics/Panel.svg | 369 + UserGuide/Graphics/hd1k.svg | 1088 +++ UserGuide/Graphics/hd512.svg | 236 + UserGuide/index.html | 5204 ++++++++++++ css/base.css | 366 + css/bootstrap.min.css | 12 + css/bootstrap.min.css.map | 1 + css/brands.min.css | 6 + css/fontawesome.min.css | 9 + css/solid.min.css | 6 + css/v4-font-face.min.css | 6 + img/favicon.ico | Bin 0 -> 1150 bytes img/grid.png | Bin 0 -> 1458 bytes index.html | 537 ++ js/base.js | 287 + js/bootstrap.bundle.min.js | 7 + js/bootstrap.bundle.min.js.map | 1 + js/darkmode.js | 65 + search/lunr.js | 3475 ++++++++ search/main.js | 109 + search/search_index.json | 1 + search/worker.js | 133 + sitemap.xml | 3 + sitemap.xml.gz | Bin 0 -> 127 bytes webfonts/fa-brands-400.ttf | Bin 0 -> 207972 bytes webfonts/fa-brands-400.woff2 | Bin 0 -> 117372 bytes webfonts/fa-regular-400.ttf | Bin 0 -> 68004 bytes webfonts/fa-regular-400.woff2 | Bin 0 -> 25452 bytes webfonts/fa-solid-900.ttf | Bin 0 -> 419720 bytes webfonts/fa-solid-900.woff2 | Bin 0 -> 156496 bytes webfonts/fa-v4compatibility.ttf | Bin 0 -> 10832 bytes webfonts/fa-v4compatibility.woff2 | Bin 0 -> 4792 bytes 48 files changed, 36683 insertions(+) create mode 100644 .nojekyll create mode 100644 404.html create mode 100644 Applications/index.html create mode 100644 Catalog/index.html create mode 100644 Hardware/index.html create mode 100644 Introduction/index.html create mode 100644 SystemGuide/Graphics/BankSwitchedMemory.svg create mode 100644 SystemGuide/Graphics/CharacterEmulationVideoServices.svg create mode 100644 SystemGuide/Graphics/Logo.svg create mode 100644 SystemGuide/Graphics/Panel.svg create mode 100644 SystemGuide/Graphics/hd1k.svg create mode 100644 SystemGuide/Graphics/hd512.svg create mode 100644 SystemGuide/index.html create mode 100644 UserGuide/Graphics/BankSwitchedMemory.svg create mode 100644 UserGuide/Graphics/CharacterEmulationVideoServices.svg create mode 100644 UserGuide/Graphics/Logo.svg create mode 100644 UserGuide/Graphics/Panel.svg create mode 100644 UserGuide/Graphics/hd1k.svg create mode 100644 UserGuide/Graphics/hd512.svg create mode 100644 UserGuide/index.html create mode 100644 css/base.css create mode 100644 css/bootstrap.min.css create mode 100644 css/bootstrap.min.css.map create mode 100644 css/brands.min.css create mode 100644 css/fontawesome.min.css create mode 100644 css/solid.min.css create mode 100644 css/v4-font-face.min.css create mode 100644 img/favicon.ico create mode 100644 img/grid.png create mode 100644 index.html create mode 100644 js/base.js create mode 100644 js/bootstrap.bundle.min.js create mode 100644 js/bootstrap.bundle.min.js.map create mode 100644 js/darkmode.js create mode 100644 search/lunr.js create mode 100644 search/main.js create mode 100644 search/search_index.json create mode 100644 search/worker.js create mode 100644 sitemap.xml create mode 100644 sitemap.xml.gz create mode 100644 webfonts/fa-brands-400.ttf create mode 100644 webfonts/fa-brands-400.woff2 create mode 100644 webfonts/fa-regular-400.ttf create mode 100644 webfonts/fa-regular-400.woff2 create mode 100644 webfonts/fa-solid-900.ttf create mode 100644 webfonts/fa-solid-900.woff2 create mode 100644 webfonts/fa-v4compatibility.ttf create mode 100644 webfonts/fa-v4compatibility.woff2 diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 00000000..e69de29b diff --git a/404.html b/404.html new file mode 100644 index 00000000..7fee56e8 --- /dev/null +++ b/404.html @@ -0,0 +1,189 @@ + + + + + + + + + + + RomWBW Documentation V3.6 + + + + + + + + + + + + + + + + +
+
+ +
+
+

404

+

Page not found

+
+
+ + +
+
+ + + + + + + + + + + diff --git a/Applications/index.html b/Applications/index.html new file mode 100644 index 00000000..8f715e80 --- /dev/null +++ b/Applications/index.html @@ -0,0 +1,3750 @@ + + + + + + + + + + + Applications - RomWBW Documentation V3.6 + + + + + + + + + + + + + + + + +
+
+
+
+ +

RomWBW Applications Guide \ +Version 3.6 \ +MartinR \& Phillip Summers () \ +30 May 2025

+

Summary

+

RomWBW is supplied with a suite of software applications that enhance +the use of the system. Some of these applications have been written +entirely from scratch for RomWBW. Others are pre-existing software that +has been customized for the RomWBW environment. This document serves as +a reference for these RomWBW-specific applications.

+

The primary usage documentation for RomWBW is the RomWBW User +Guide. +It is assumed that the reader is generally familiar with this document.

+

RomWBW also includes many generic software applications that have not +been modified for RomWBW (e.g., MSBASIC). These generic applications are +not documented here. Please refer to the application specific +documentation for these generic applications. The documentation for some +of these generic applications is included in the Doc folder of the +RomWBW distribution.

+

The applications described in this document fall into two general +categories.

+
    +
  1. +

    ROM Applications are software applications that are loaded from + the the ROM memory of your RomWBW system.

    +
  2. +
  3. +

    CP/M Applications are software applications that are loaded from + disk using a previously loaded CP/M (or CP/M like) operating system + using its command line.

    +
  4. +
+

Note that some applications are available in both forms. For example, +Microsoft BASIC is available as a ROM application and as an application +that runs under CP/M. Only the ROM variant is documented here because +the CP/M variant is not RomWBW-specific.

+

You will see that two of the RomWBW operating systems are included here +as ROM Applications. Although operating systems are normally loaded from +disk, RomWBW does include a way to launch CP/M 2.2 and Z-System directly +from ROM.

+

Most RomWBW systems include a ROM disk. A running operating system can +load applications from the ROM disk just like a floppy or hard disk. +Applications loaded from the ROM disk by CP/M are considered to be CP/M +applications, not ROM applications.

+

Boot Menu

+

The system start-up process is described in some detail in the RomWBW +User Guide, and for the sake of completeness there is some overlap here.

+

When a RomWBW system is started the user is presented with a sign-on +message at the default console detailing the RomWBW version and build +date. The system follows this with the list of hardware that it has +discovered, a list of devices and the system units assigned to them, +before finally inviting the to select a boot device with the prompt:

+
Boot [H=Help]:
+
+

At this point, the user may specify a unit, optionally with a slice, to +boot from. Note that it is not possible to boot from from the serial +(ASCI) or memory disk (MD) devices.

+

Alternatively the user may select one of the built-in Boot Loader +commands. A menu of which may be displayed by pressing the H or ? keys +(for Help). Furthermore, a ROM application may also be started from this +prompt.

+

This start-up process is described in some detailed in the RomWBW User +Guide, and there is some overlap here.

+

Help

+

After pressing H or ? at the boot prompt the user will be presented with +the following list of available commands:

+
L           - List ROM Applications
+D           - Device Inventory
+R           - Reboot System
+I <u> [<c>] - Set Console Interface/Baud code
+V [<n>]     - View/Set HBIOS Diagnostic Verbosity
+<u>[.<s>]   - Boot Disk Unit/Slice
+
+

The function performed by each command is described below:

+

L:
+Lists the applications and operating systems that are built into the +RomWBW ROM - e.g., low-level monitor utility, CP/M, or BASIC.

+

D:
+Displays the list of system devices that was first displayed when the +system was started.

+

R:
+Will restart the system. Note that this does not reset hardware devices +in the same way that power-on or pressing the reset button would.

+

I:
+Allows the user to select the interface connected to the console, and +optionally the Baud rate. This could be used to allow the system to be +operated from a second console.

+

V:
+Enables the display of invalid RomWBW HBIOS API calls. This option is +very unlikely to be used by a user and is used for development purposes.

+

And, finally, the system may be booted by specifying the unit number, +and optional slice, separated by a period(‘.’), of where the disk +operating system software is located - eg 2, 4.1, 5.3

+

Alternatively, a RomWBW ROM application may be started by pressing the +appropriate key from the applications menu, shown in the following +section.

+

List ROM Applications

+

If the user presses the L key at the Boot Loader prompt then the system +will display the list of ROM applications that are built into RomWBW. If +a command letter is known, then it may be entered directly at the prompt +rather than first displaying the menu.

+

The ROM applications available from the boot prompt are:

+
M: Monitor
+C: CP/M 2.2
+Z: Z-System
+B: BASIC
+T: Tasty BASIC
+F: Forth
+P: Play a Game
+N: Network Boot
+X: XModem Flash Updater
+U: User App
+
+

Each of these will now be described in greater detail.

+

ROM Applications

+

Monitor

+

The Monitor program is a low-level utility that can be used for testing +and programming. It allows programs to be entered, memory to be examined +and modified, and input/output devices to be read or written to.

+

It’s key advantage is that is available at boot up.

+

Its key disadvantages are that code cannot be entered in assembly +language and there is no ability to save to persistent storage (disks).

+

The available memory area for programming is 0100h-EDFFh. The +following areas are reserved:

+ + + + + + + + + + + + + + + + + + + + + +
Memory AreaFunction
0000-00FFhJump and restart (RST) vectors
EE00-FDFFhMonitor
FE00-FFFFhHBIOS proxy
+

The monitor uses a prompt in the format of xx> where xx is the RomWBW +bank id number. For example, the prompt may look like this and means +that Bank Id 0x8E is currently mapped into the low 32K of processor +memory.

+

8E>

+

Please refer to Section 4 of the \$doc_sys# for a description of the +RomWBW Bank Id and how it relates to the physical bank of memory being +mapped to the lower 32K of the processor. The method of assigning banks +for specific RomWBW functions is also described.

+

Commands can be entered at the command prompt. Automatic case conversion +takes place on command entry and all numeric arguments are expected to +be in hex format.

+

The Monitor allows access to all memory locations but ROM and Flash +memory cannot be written to. At startup, the Monitor will select the +default “User” bank. The S command is provided to allow selecting +alternate banks.

+

There now follows a more detailed guide to using the RomWBW Monitor +program:

+

Command Summary

+

? - Will display a summary of the available commands.

+
Monitor Commands (all values in hex):
+B                    - Boot system
+D xxxx [yyyy]        - Dump memory from xxxx to yyyy
+F xxxx yyyy zz       - Fill memory from xxxx to yyyy with zz
+H                    - Halt system
+I xxxx               - Input from port xxxx
+K                    - Keyboard echo
+L                    - Load Intel hex data
+M xxxx yyyy zzzz     - Move memory block xxxx-yyyy to zzzz
+O xxxx yy            - Output value yy to port xxxx
+P xxxx               - Program RAM at address xxxx
+R xxxx [[yy] [zzzz]] - Run code at address xxxx
+                       Pass yy and zzzz to register A and BC
+S xx                 - Set bank to xx
+U                    - Set bank to previous bank
+T xxxx               - X-modem transfer to memory location xxxx
+X                    - Exit monitor
+
+

Cold Boot

+

B - Performs a cold boot of the RomWBW system. A complete +re-initialization of the system is performed and the system returns to +the Boot Loader prompt.

+

Dump Memory

+

D xxxx [yyyy] - Dump memory from hex location xxxx to yyyy on the +screen as lines of 16 hexadecimal bytes with their ASCII equivalents (if +within a set range, else a ‘.’ is printed). If the end address is +omitted then 256 bytes are displayed.

+

A good tool to see where code is located, check for version id, obtain +details for chip configurations and execution paths.

+

Example: D 100 1FF

+
0100: 10 0B 01 5A 33 45 4E 56 01 00 00 2A 06 00 F9 11  ...Z3ENV...*..ù.
+0110: DE 38 37 ED 52 4D 44 0B 6B 62 13 36 00 ED B0 21  Þ87íRMD.kb.6.í°!
+0120: 7D 32 E5 21 80 00 4E 23 06 00 09 36 00 21 81 00  }2å!..N#...6.!..
+0130: E5 CD 6C 1F C1 C1 E5 2A C9 8C E5 CD 45 05 E5 CD  åÍl.ÁÁå*É.åÍE.åÍ
+0140: 59 1F C3 00 00 C3 AE 01 C3 51 04 C3 4C 02 C3 57  Y.Ã..î.ÃQ.ÃL.ÃW
+0150: 02 C3 64 02 C3 75 02 C3 88 02 C3 B2 03 C3 0D 04  .Ãd.Ãu.Ã..ò.Ã..
+0160: C3 19 04 C3 22 04 C3 2A 04 C3 35 04 C3 40 04 C3  Ã..Ã".Ã*.Ã5.Ã@.Ã
+0170: 48 04 C3 50 04 C3 50 04 C3 50 04 C3 8F 02 C3 93  H.ÃP.ÃP.ÃP.Ã..Ã.
+0180: 02 C3 94 02 C3 95 02 C3 85 04 C3 C7 04 C3 D1 01  .Ã..Ã..Ã..ÃÇ.ÃÑ.
+0190: C3 48 02 C3 E7 04 C3 56 03 C3 D0 01 C3 D0 01 C3  ÃH.Ãç.ÃV.ÃÐ.ÃÐ.Ã
+01A0: D0 01 C3 D0 01 C3 D0 01 C3 D0 01 01 02 01 CD 6B  Ð.ÃÐ.ÃÐ.ÃÐ....Ík
+01B0: 04 54 68 69 73 20 66 75 6E 63 74 69 6F 6E 20 6E  .This function n
+01C0: 6F 74 20 73 75 70 70 6F 72 74 65 64 2E 0D 0A 00  ot supported....
+01D0: C9 3E FF 32 3C 00 3A 5D 00 FE 20 28 14 D6 30 32  É>ÿ2<.:].þ (.Ö02
+01E0: AB 01 32 AD 01 3A 5E 00 FE 20 28 05 D6 30 32 AC  «.2­.:^.þ (.Ö02¬
+01F0: 01 C5 01 F0 F8 CF E5 26 00 0E 0A CD 39 02 7D 3C  .Å.ðøÏå&...Í9.}<
+
+

Fill Memory

+

F xxxx yyyy zz - Fill memory from hex xxxx to yyyy with a single +value of zz over the full range. The Dump command can be used to confirm +that the fill completed as expected. A good way to zero out memory areas +before writing machine data for debug purposes.

+

Halt System

+

H - Halt system. A Z80 HALT instruction is executed. The system +remains in the halt state until the system is physically rebooted. +Interrupts will not restart the system. On systems that support a HALT +status LED, the LED will be illuminated.

+

Input from Port

+

I xxxx - Input data from port xxxx and display to the screen. This +command is used to read values from hardware I/O ports and display the +contents in hexadecimal.

+

Keyboard Echo

+

K - Echo any key-presses from the terminal. Press ‘ESC’ key to +quit. This facility provides that any key stroke sent to the computer +will be echoed back to the terminal. File down loads will be echoed as +well while this facility is ‘on’.

+

Load Hex

+

L - Load a Intel Hex data via the terminal program. The load +address is defined in the hex file of the assembled code.

+

The terminal emulator program should be configured to give a delay at +the end of each line to allow the monitor enough time to parse the line +and move the data to memory.

+

Keep in mind that this will be transient unless the system supports +battery backed memory. Saving to memory drive is not supported.

+

Move Memory

+

M xxxx yyyy zzzz - Move hex memory block xxxx to yyyy to memory +starting at hex location zzzz. Care should be taken to insure that there +is enough memory at the destination so that code does not get +over-written or memory wrapped around.

+

Output to Port

+

O xxxx yy - Output data byte xx to port xxxx. This command is used +to send hexadecimal values to hardware I/O ports to verify their +operation and is the companion to the I operation. Use clip leaded LEDs +to confirm the data written.

+

Program Memory

+

P xxxx - Program memory location xxxx. This routine will allow you +to program a hexadecimal value ‘into memory starting at location xxxx. +Press ’Enter’ on a blank line to return to the Monitor prompt.

+

The limitation around programming memory is that it must be entered in +hexadecimal. An alternative is to use the L command to load a program +that has been assembled to a hex file on the remote computer.

+

An excellent online resource for looking up opcodes for entry can be +found here: https://clrhome.org/table.

+

Run Program

+

R xxxx [[yy] [zzzz]] - Run program at location xxxx. If optional +arguments yy and zzzz are entered they are loaded into the A and BC +register respectively. The return address of the Monitor is saved on the +stack so the program can return to the monitor. On return to the +monitor, the contents of the A, HL, DE and BC registers are displayed.

+

Set Bank

+

S xx - Set the physical memory bank to the RomWBW Bank Id +indicated by xx. Memory addresses 0x0000-0x7FFF (i.e. bottom 32k) are +affected. Because the interrupt vectors are stored in the bottom page of +this range, this function is disabled when interrupt mode 1 is being +used (IM1). Interrupt mode 2 is not affected as the associated jump +vectors are stored in high memory.

+

Changing the bank also impacts the restart vectors (RST), so executing +code that calls the HBIOS using the RST 08 assembly code will not +work.

+

The monitor stack resides in high memory and is not affected but any +code that changes the stack to low memory will be affected.

+

The U command may be used to undo the change and return the selected +memory bank back to the previously selected one.

+

Section 4 of the RomWBW System +Guide +provides detail on how Bank Ids map to the physical memory of the system +and also how specific banks are utilized by RomWBW.

+

Undo Bank

+

U - Change the bank in memory back to the previously selected +bank. This command should be used in conjunction with the S command.

+

X-Modem Transfer

+

T xxxx - Receive an X-modem file transfer and load it into memory +starting at location xxxx.

+

128 byte blocks and checksum mode is the only supported protocol.

+

Exit Monitor

+

X - Exit the monitor program back to the main boot menu.

+

RomWBW System Configuration

+

System Configuration (SYSCONF) is a utility that allows system +configuration to be set, dynamically and stored in NVRAM provided by an +RTC chip.

+

(SYSCONF) is both a ROM application (‘W’ Menu option), and a CP/M +utility. Noting however the CP/M utility is not included on an disk +image, it is found in the Binary/Applications folder of the RomWBW +distribution.

+

The RomWBW User +Guide +has additional information on the use of NVRAM to set your system +configuration.

+

Basic Operation

+

The application is an interactive application; it does not have a +command line syntax. Instead commands are executed from within the +application in a command line structure.

+

When you first start the (SYSCONF) utility it will display the current +switches followed by a command listing.

+

When you first run the (SYSCONF) utility the NVRAM will be +uninitialised, and can be initialised using the (R)eset command, which +writes default values to NVRAM.

+

Updates are done immediately to NVRAM as you enter them, i.e. there is +no confirm changes step. If you make any incorrect changes, you simply +need to enter a new command to set the Switch value correctly.

+

Once a change has been made it is available, however it may not take +effect until the next system reboot. This is dependent on the Switch +itself.

+

If no NVRAM is provided by your hardware, then running this application +will just report the missing hardware and exit immediately.

+

To exit from the application use the (Q)uit command.

+

Commands and Syntax

+

The following are the accepted commands, unless otherwise specified a +“Space” character is used to delimit parameters in the command.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CommandArgument(s)Description
(P)rint-none-Display a list of the current switch value(s)
(S)et{SW} {val},…Sets an Switch {SW} with specific values(s)
(R)eset-none-Reset all setting to default
(H)elp{SW}Provides help on the syntax (values)
(Q)uit-none-Exit the application
+

Where

+ + + + + + + + + + + + + + + + + +
ArgumentDescription
{SW}Switch ID, typically this is 2 character name to identify the switch
{val},…a “Comma” separated list of values to set into the switch
+

Switch Options

+

Auto Boot (AB)

+

This switch will define if the system will perform auto boot at the +RomWBW boot prompt. Enabling this will not prevent a user from typing a +boot command, so long as the timeout is not exceeded. When configured +this replaces the (AUTO_CMD) variable defined in build configuration.

+

Making changes to auto boot has no affect until the next reboot.

+

Arguments

+ + + + + + + + + + + + + + + + + + + + + + + + + +
TypeArgumentsDescription
Enable‘E’Auto Boot. eg. “E,10” will auto boot, after 10 seconds
TimoutTimeout in seconds in the range 0-15, 0 = immediate
Disabled‘D’No Auto Boot. e.g. “D” will disable autoboot
+

Examples

+ + + + + + + + + + + + + + + + + +
CommandDescription
S AB E,10Enable Auto Boot with 10 second delay
S AB DDisable Auto Boot
+

Boot Options (BO)

+

This switch will define the boot command to be executed when auto boot +is enabled. When configured this replaces the (AUTO_CMD) variable +defined in the ROM build configuration.

+

Making changes to boot options has no affect until the next reboot.

+

Arguments

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TypeArgumentsDescription
Disk‘D’Disk Boot. eg. “D,2,14” will boot, disk unit 2, slice 14
Disk Unit NumberUnit number in the range 0-127
Disk SliceSlice in the range 0-255, use 0 for floppy boot
ROM‘R’ROM App. e.g. “R,M” will boot the Monitor App
Rom App Namesingle character used on the Menu to identify the app
+

Examples

+ + + + + + + + + + + + + + + + + +
CommandDescription
S BO D,2,14Set the default boot from Disk; Unit 2, Slice 14
S BO R,MSet the default boot to be the (M)onitor Rom Application
+

CP/M 2.2

+

This option will boot the CP/M 2.2 disk operating system from an image +contained within the ROM. Please refer to the CPM User Manual in the +Doc/CPM folder of the distribution for CP/M usage. There are also many +online resources.

+

During the build process the system will create a ROM disk containing a +number of curated CP/M applications, and also a RAM drive. The capacity +of each will depend upon the size of the ROM and RAM available to the +system. A more complete set of utilities are provided within the disk +image files provided as part of RomWBW.

+

A number of the applications provided are generic to CP/M, while others +rely on particular hardware or aspects of RomWBW itself.

+

Those that are written specific to RomWBW include: ASSIGN, CPUSPD, FDU, +FORMAT, FLASH, FDISK80, MODE, REBOOT, RTC, SYSCOPY, TALK, TIMER, XM, and +COPYSL.

+

The CP/M utilities supplied with RomWBW warrant more detailed +descriptions, and so are described in some detail in their own section +of this user guide. In summary they provide the initial capability to +manage and update your RomWBW system, to create other bootable media +(hardware dependent) and to write/debug code using assembler and BASIC.

+

Z-System

+

Z-System is a complete alternative, but entirely compatible, disk +operating system to CP/M.

+

Z-System is comprised of ZSDOS 1.1 which is a replacement for CP/M’s +Basic Disk Operating System (BDOS), and ZCPR which is a replacement for +the Console Command Processor (CCP). Either or both may be used, +although using both together will allow ZCPR to make use of specific +ZSDOS features.

+

Documentation for Z-System may be found in the Doc/CPM folder of the +RomWBW distribution and the reader is referred to those.

+

BASIC

+

For those who are not familiar with BASIC, it stands for Beginners All +Purpose Symbolic Instruction Code.

+

RomWBW contains two versions of ROM BASIC, a full implementation and a +“tiny” BASIC.

+

The full implementation is a version of Microsoft BASIC from the NASCOM +Computer.

+

A comprehensive instruction manual is available in the Doc/Contrib +directory.

+

RomWBW specific features

+
    +
  • Sound
  • +
  • Graphics
  • +
  • Terminal Support
  • +
+

RomWBW unsupported features

+
    +
  • Cassette loading
  • +
  • Cassette saving
  • +
+

TastyBASIC

+

TastyBASIC offers a minimal implementation of BASIC that is only 2304 +bytes in size. It originates from Li-Chen Wang’s Palo Alto Tiny BASIC +from around 1976. It’s small size is suited the tiny memory capacities +of the time. This implementation is by Dimitri Theulings and his +original source can be found at +https://github.com/dimitrit/tastybasic.

+

Features / Limitations

+
    +
  • Integer arithmetic, numbers -32767 to 32767
  • +
  • Singles letter variables A-Z
  • +
  • 1-dimensional array support
  • +
  • Strings are not supported
  • +
+

Direct Commands

+
    +
  • LIST,RUN, NEW, CLEAR, BYE
  • +
+

Statements

+
    +
  • LET, IF, GOTO, GOSUB RETURN, REM, FOR TO NEXT STEP, + INPUT, PRINT, POKE, END
  • +
+

Functions

+
    +
  • PEEK, RND, ABS, USR, SIZE
  • +
+

Operators

+
    +
  • +

    >=, #, >, =, <=, <

    +
  • +
  • +

    Operator precedence is supported.

    +
  • +
+

Type BYE to return to the boot menu.

+

FORTH

+

CamelForth is the version of Forth included as part of the boot ROM in +RomWBW. It has been converted from the Z80 CP/M version published at +https://www.camelforth.com/page.php?5. The author is Brad Rodriguez +who is a prolific Forth enthusiast, whose work can be found here: +https://www.bradrodriguez.com/papers.

+

For those are who are not familiar with Forth, I recommend the wikipedia +article https://en.wikipedia.org/wiki/Forth_(programming_language) and +the Forth Interest Group website https://www.forth.org/.

+

Important things to know

+

Forth is case sensitive.

+

To exit back to the boot loader type bye

+

To get a list of available words type WORDS

+

To reset Forth to its initial state type COLD

+

Most of the code you find on the internet will not run unless modified +or additional Forth words are added to the dictionary.

+

This implementation does not support loading or saving of programs. All +programs need to be typed in. Additionally, screen editing and code +blocks are not supported.

+

A CP/M version is not provided with RomWBW, this is only a ROM +application. If you need to run it under CP/M you would need to download +it from the camelforth web site, the link is above.

+

Structure of Forth source files

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileDescription
camel80.azmCode Primitives
camel80d.azmCPU Dependencies
camel80h.azmHigh Level words
camel80r.azmRomWBW additions
glosshi.txtGlossary of high level words
glosslo.txtGlossary of low level words
glossr.txtGlossary of RomWBW additions
+

RomWBW Additions

+

Extensions and changes to this implementation compared to the original +distribution are:

+
    +
  • +

    The source code has been converted from Z80mr assembler to Hector + Peraza’s zsm.

    +
  • +
  • +

    An additional file camel80r.azm has been added for including + additional words to the dictionary at build time. However, as + currently configured there is very little space allocated for addition + words. Exceeding the allocated ROM space will generate an error + message when building.

    +
  • +
  • +

    James Bowman’s double precision words have been added from his RC2014 + version: https://github.com/jamesbowman/camelforth-z80.

    +
  • +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
WordSyntaxDescription
D+d1 d2 – d1+d2Add double numbers
2>Rd –2 to R
2R>d –fetch 2 from R
M*/d1 n2 u3 – d=(d1*n2)/u3double precision mult. div
SVChl de bc n – hl de bc afExecute a RomWBW function
P!n p –Write a byte to a I/O port
P@p – nRead a byte from and I/O port
+

Play a Game

+

2048

+

2048 is a puzzle game that can be both mindless and challenging. It +appears deceptively simple but failure can creep up on you suddenly.

+

It requires an ANSI/VT-100 compatible colour terminal to play.

+

2048 is like a sliding puzzle game except the puzzle tiles are numbers +instead of pictures. Instead of moving a single tile all tiles are moved +simultaneously in the same direction. Where two tiles of the same number +collide, they are reduced to one tile with the combined value. After +every move a new tile is added with a starting value of 2.

+

The goal is to create a tile of 2048 before all tile locations are +occupied. Reaching the highest points score, which is the sum of all the +tiles is a secondary goal. The game will automatically end when there +are no more possible moves.

+

Play consists of entering a direction to move. Directions can be entered +using any of three different keyboard direction sets.

+
Direction | Keys
+----------|----------
+Up        | w ^E 8
+Down      | s ^X 2
+Left      | a ^S 4
+Right     | d ^D 6
+
+

The puzzle board is a 4x4 grid. At start, the grid will be populated +with two 2 tiles. An example game sequence is shown below with new tiles +to the game shown in brackets.

+
Start             Move 1 - Up       Move 2 - Left     Move 3 - Left
++---+---+---+---+ +---+---+---+---+ +---+---+---+---+ +---+---+---+---+
+|   |   |   |(2)| |   |   |   | 4 | | 4 |   |   |   | | 4 |   |   |   |
++---+---+---+---+ +---+---+---+---+ +---+---+---+---+ +---+---+---+---+
+|   |   |   |   | |   |   |   |   | |   |   |   |(4)| | 4 |   |   |   |
++---+---+---+---+ +---+---+---+---+ +---+---+---+---+ +---+---+---+---+
+|   |   |   |(2)| |   |   |   |   | |   |   |   |   | |   |   |   |   |
++---+---+---+---+ +---+---+---+---+ +---+---+---+---+ +---+---+---+---+
+|   |   |   |   | |   |   |(2)|   | | 2 |   |   |   | | 2 |   |(2)|   |
++---+---+---+---+ +---+---+---+---+ +---+---+---+---+ +---+---+---+---+
+
+Move 4 - Left     Move 5 - Up       Move 6 - Right    Move 7 - Up
++---+---+---+---+ +---+---+---+---+ +---+---+---+---+ +---+---+---+---+
+| 4 |   |   |   | | 8 |   |   | 4 | |   |   | 8 | 4 | |   |   | 8 | 8 |
++---+---+---+---+ +---+---+---+---+ +---+---+---+---+ +---+---+---+---+
+| 4 |   |   |(4)| | 4 |   |   |   | |   |   |   | 4 | |   |   |   | 2 |
++---+---+---+---+ +---+---+---+---+ +---+---+---+---+ +---+---+---+---+
+|   |   |   |   | |   |   |   |   | |   |   |   |   | |   |   |   |   |
++---+---+---+---+ +---+---+---+---+ +---+---+---+---+ +---+---+---+---+
+| 4 |   |   |   | |(2)|   |   |   | |(2)|   |   | 2 | |(2)|   |   |   |
++---+---+---+---+ +---+---+---+---+ +---+---+---+---+ +---+---+---+---+
+
+

This is how I lost this game:

+
+---+---+---+---+
+| 4 | 2 | 16| 4 |
++---+---+---+---+
+| 32| 64| 8 | 2 |
++---+---+---+---+
+| 4 | 8 |128| 32|
++---+---+---+---+
+|(2)| 16| 8 | 4 |
++---+---+---+---+
+
+

Press Q at any time to bring up the option to Quit or Restart the game.

+

Network Boot

+

If your RomWBW system is equipped with an RCBus MT011 module, it is +possible to boot into CP/M 2.2 directly from a CP/NET network server. +This means that the operating system will be loaded directly from the +network server and all of your drive letters will be provided by the +network server.

+

This function requires substantial knowledge of CP/NET and it’s +implementation within RomWBW. Section 10 of the RomWBW User +Guide +provides complete instructions for setting up a CP/NET based network +under RomWBW including a section on network booting.

+

Xmodem Flash Updater

+

The RomWBW Xmodem flash updater provides the capability to update RomWBW +from the boot loader using an x-modem file transfer. It offers similar +capabilities to Will Sowerbutts FLASH4 utility except that the flashing +process occurs during the file transfer.

+

These are the key differences between the two methods are:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Xmodem Flash UpdaterFLASH.COM (aka FLASH4)
Available from the boot loaderWell proven and tested
Xmodem transfer is integratedWider range of supported chips and hardware
Integrated checksum utilitiesWider range of supported platforms
Capability to copy a ROM imageOnly reprograms sectors that have changed
More convenient one step processAbility save and verify ROM images
No intermediate storage requiredProgress display while flashing
.Displays chip identification information
.Faster file transfer
+

The major disadvantages of the Updater is that it is new and relatively +untested. There is the risk that a failed transfer will result in a +partially flashed and unbootable ROM. There are some limitations on +serial transfer speeds.

+

The updater utility was initially intended to support the Retrobrew +SBC-V2-005 platform using Atmel 39SF040 flash chips but has now been +extended to be more generic in operation.

+

Supported flash chips are 39SF040, 29F040, AT49F040, AT29C040, M29F040 , +MX29F040, A29010B, A29040B

+

The Atmel 39SF040 chip is recommended as it can erase and write 4Kb +sectors. Other chips require the whole chip to be erased.

+

Usage

+

In most cases, completing a ROM update is a simple as:

+
    +
  1. Booting to the boot loader prompt
  2. +
  3. Selecting option X - Xmodem Flash Updater
  4. +
  5. Selecting option U - Update
  6. +
  7. Initiating an X-modem transfer of your ROM image on your console + device
  8. +
  9. Selecting option R - Reboot
  10. +
+

If your console device is not able to transfer a ROM image i.e. your +console is a VDU then you will have to use the console options to +identify which character-input/output device is to be used as the serial +device for transfer.

+

When your console is the serial device used for the transfer, no +progress information is displayed as this would disrupt the x-modem file +transfer. If you use an alternate character-input/output devices as the +serial device for the transfer then progress information will be +displayed on the console device.

+

Due to different platform processor speeds, serials speeds and flow +control capabilities the default console or serial device speed may need +to be reduced for a successful transfer and flash to occur. The Set +Console Interface/Baud code option at the Boot Loader can be used to +change the speed if required. Additionally, the Updater has options to +set to and revert from a recommended speed.

+

See the RomWBW Applications guide for additional information on +performing upgrades.

+

Console Options

+

Option ( C ) - Set Console Device

+

Option ( S ) - Set Serial Device

+

By default the updater assumes that the current console is a serial +device and that the ROM file to be flashed will also be transferred +across this device, so the Console and Serial device are both the same.

+

Either device can be can be change to another character-input/output +device but the updater will always expect to receive the x-modem +transfer on the Serial Device

+

The advantage of transferring on a different device to the console is +that progress information can be displayed during the transfer.

+

Option ( > ) - Set Recommended Baud Rate

+

Option ( \< ) - Revert to Original Baud Rate

+

Programming options

+

Option ( U ) - Begin Update

+

The will begin the update process. The updater will expect to start +receiving an x-modem file on the serial device unit.

+

X-modem sends the file in packets of 128 bytes. The updater will cache +32 packets which is 1 flash sector and then write that sector to the +flash device.

+

If using separate console, bank and sector progress information will +shown

+
BANK 00 s00 s01 s02 s03 s04 s05 s06 s06 s07
+BANK 01 s00 s01 s02 s03 s04 s05 s06 s06 s07
+BANK 02 s00 s01 s02 s03 s04 s05 s06 s06 s07 etc
+
+

The x-modem file transfer protocol does not provide any filename or size +information for the transfer so the updater does not perform any checks +on the file suitability.

+

The updater expects the file size to be a multiple of 4 kilobytes and +will write all data received to the flash device. A system update file +(128kb .img) or complete ROM can be received and written (512kb or +1024kb .rom)

+

If the update fails it is recommended that you retry before rebooting or +exiting to the Boot loader as your machine may not be bootable.

+

Option ( D ) - Duplicate flash #1 to flash #2

+

This option will make a copy of flash #1 onto flash #2. The purpose of +this is to enable making a backup copy of the current flash. Intended +for systems using 2x512Kb Flash devices.

+

Option ( V ) - Toggle Write Verify

+

By default each flash sector will be verified after being written. +Slight performance improvements can be gained if turned off and could be +used if you are experiencing reliable transfers and flashing.

+

Exit options

+

Option ( R ) - Reboot

+

Execute a cold reboot. This should be done after a successful update. If +you perform a cold reboot after a failed update then it is likely that +your system will be unusable and removing and reprogramming the flash +will be required.

+

Option ( Q ) - Quit to boot loader.

+

The SBC Boot Loader is reloaded from ROM and executed. After a +successful update a Reboot should be performed. However, in the case of +a failed update this option could be used to attempt to load CP/M and +perform the normal x-modem / flash process to recover.

+

CRC Utility options

+

Option ( 1 ) and ( 2 ) - Calculate and display CRC32 of 1st or 2nd 512k +ROM. Option ( 3 ) - Calculate and display CRC32 of a 1024k (2x512Kb) +ROM.

+

Can be used to verify if a ROM image has been transferred and flashed +correctly. Refer to the Tera Term section below for details on +configuring the automatic display of a files CRC after it has been +transferred.

+

In Windows, right clicking on a file should also give you a context menu +option CRC SHA which will allow you to select a CRC32 calculation to be +done on the selected file.

+

Tera Term macro configuration

+

Macros are a useful tool for automatic common tasks. There are a number +of instances where using macros to facilitate the update process could +be worthwhile if you are:

+
    +
  • Following the RomWBW development builds.
  • +
  • Doing lots of configuration changes.
  • +
  • Doing development on RomWBW drivers
  • +
+

Macros can be used to automate sending ROM updates or images and for my +own purposed I have set up a separate macro for transferring each of the +standard build ROM, my own custom configuration ROM and update ROM.

+

An example macro file to send an *.upd file, using checksum mode and +display the crc32 value of the transmitted file:

+
Xmodem send, checksum, display crc32
+xmodemsend '\\desktop\users\phillip\documents\github\romwbw\binary\sbc_std_cust.upd' 1
+crc32file crc '\\desktop\users\phillip\documents\github\romwbw\binary\sbc_std_cust.rom'
+sprintf '0x%08x' crc
+messagebox inputstr 'crc32'
+
+

Serial speed guidelines

+

As identified in the introduction, there are limitations on serial speed +depending on processor speed and flow control settings. Listed below are +some of the results identified during testing.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ConfigurationProcessor SpeedMaximum Serial Speed
UART no flow control2MHz9600
UART no flow control4MHz19200
UART no flow control5MHz19200
UART no flow control8MHz38400
UART no flow control10MHz38400
USB-fifo 2MHz+n/a
ASCI no flow control18.432MHz9600
ASCI with flow control18.432MHz38400
+

The Set Recommend Baud Rate option in the Updater menu follows the +following guidelines.

+ + + + + + + + + + + + + + + + + + + + + + + + + +
Processor SpeedBaud Rate
1MHz4800
2-3MHz9600
4-7MHz19200
8-20MHz38400
+

These can be customized in the updater.asm source code in the CLKTBL +table if desired. Feedback to the RomWBW developers on these guidelines +would be appreciated.

+

Notes

+

All testing was done with Tera Term x-modem, Forcing checksum mode using +macros was found to give the most reliable transfer. Partial writes can +be completed with 39SF040 chips. Other chips require entire flash to be +erased before being written. An SBC V2-005 MegaFlash or Z80 MBC required +for 1mb flash support. The Updater assumes both chips are same type +Failure handling has not been tested. Timing broadly calibrated on a Z80 +SBC-v2 Unabios not supported

+

User Application

+

RomWBW provides the facility for a user to build, include and execute +their own custom application directly from the applications menu at +boot-up. All that’s needed is for the user to create their custom code +ready for inclusion, recognising that there are certain constraints in +doing this.

+

In order to build properly, the build process requires that the file +usrrom.asm be found in the /Source/HBIOS folder of the RomWBW tree.

+

This source file needs to assemble using TASM and it must start at (ORG) +address 00100H as the RomWBW HBIOS reserves locations 00000H to 000FFH +for internal use. Further, the user application must assemble to a +maximum of USR-SIZ bytes.

+

During execution, the user application may make use of HBIOS calls as +necessary, and at exit it should return to the RomWBW boot loader using +the HBIOS warm reset. Note that no disk operating system (eg CP/M) +functions will be available as no disk operating system will have been +loaded.

+

There is a sample usrrom.asm supplied in Source/HBIOS and it is +recommended that, at least initially, users create their own application +based on this as a template because it already creates the necessary +variables, starts at (ORG) 00100H, and ensures that the assembled file +is padded to create a file USR-SIZ in length. Equally, should the the +user’s application prove too large for the space available then assembly +will be terminated with an error. Users should not remove this check +from the templated code.

+

If required, the user application may make use of the Z80 interrupt +system but if the user application wishes to rely on HBIOS functionality +then it must adhere to the HBIOS framework for managing interupts. +Alternatively, if the user appliction has no need for the HBIOS then it +may use its own custom code for handling interrupts. In that case, a +hard reset, rather than an HBIOS warm start, would be necessary to +return control to RomWBW.

+

CP/M Applications - ROM-Based & Disk-Based

+

There now follows a more detailed guide to using the small suite of +custom applications included with RomWBW. In general, these applications +are operating system agnostic – they run under any of the included +operating systems. However, they all require RomWBW – they are not +generic CP/M applications.

+

Most of the applications are custom written for RomWBW. However, some +are standard CP/M applications that have been adapted to run under +RomWBW (e.g. XM/XModem). The applications are generally matched to the +version of RomWBW they are distributed with. So, if you upgrade the +version of RomWBW in your system ROM, you will want to copy the +corresponding applications to any storage devices you are using.

+

Most of the applications are included on the RomWBW ROM disk, so they +are easy to access.

+

The applications are also included with all of the operating system disk +images provided with RomWBW. So, a simple way to ensure you have +matching applications is to write the disk images onto your disk media +when upgrading your ROM. Of course, this will destroy any existing data +on your disk media, so don’t do this if you are saving any data on the +media.

+

Most of the applications are included as source code in the RomWBW +distribution and are built during the normal build process. The source +code is found in the Source/Apps directory of the distribution. The +binary executable applications are found in the Binary/Apps directory.

+

The table below clarifies where each of the applications may be found. +It is not an exhaustive list, with further applications existing on both +the ROM-based and disk-based versions of CP/M. All of the Applications +included within RomWBW may be found within the Binary/Apps directory.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ApplicationROM DiskBoot Disks
ASSIGNYesYes
BBCBASICNoYes
CLRDIRYesYes
COPYSLNoYes
CPUSPDYesYes
FATNoYes
FDISK80YesYes
FDUYesYes
FLASHYesYes
FORMATYesYes
HTALKYesYes
MODEYesYes
REBOOTYesYes
RTCYesYes
SURVEYYesYes
SYSCOPYYesYes
TALKYesYes
TBASICNoYes
TIMERYesYes
TUNENoYes
VGMPLAYNoYes
WDATENoYes
XMYesYes
ZMDNoYes
ZMPNoYes
+

All of the CP/M applications may be found in the RomWBW Binary/Apps +directory and a user may copy those they need to their own customized +disk/slice.

+

Independently of whether the CP/M system was started from ROM or a boot +disk, such as a floppy disk or a slice on a CF or uSD memory card, +applications may be located on and executed from either the ROM-disk +itself or from other media. There are multiple disk images available for +CP/M (eg floppy, legacy hard-disk and new hard-disk formats) and they +all contain essentially the same set of applications.

+

There are particular advantages for each method of booting into CP/M.

+

ROM-based CP/M:

+
    +
  • A clean and reliable copy of CP/M with no possibility of corruption
  • +
  • No additional hardware required
  • +
  • Fast to boot
  • +
  • Rolled forward with new releases of RomWBW
  • +
+

Disk-based CP/M:

+
    +
  • Greater capacity allows for a larger number of applications
  • +
  • Allows for user-customisation of applications available
  • +
  • Allows individual disks to be tailored to a particular purpose, eg + word processor
  • +
+

For systems starting CP/M from a disk created from an image file, there +are a small number of additional applications stored in the USER 2 +area of the disk. These applications do not form part of CP/M, but +rather are small utilities used for test purposes during develpment +work. They may, or may not, fuction correctly with any given hardware or +software configuration. Documentation for these untilities is very +limited, though the source files maybe found in the /Source folder. Note +that these utiltites are not available when starting CP/M from the ROM +image or from a floppy disk.

+

A number of the CP/M applications available are described in more detail +in the following sections, each with an indication as to whether that +application may be found on the ROM-disk, a boot-disk, or both.

+

ASSIGN

+ + + + + + + + + + + + + + + + + +
ASSIGN
ROM-basedYes
Disk-basedYes
+

RomWBW includes a flexible mechanism for associating the operating +system drive letters (A: - P:) to the physical devices in the system. +Drive letter assignments can be changed on a running operating system +without rebooting. The ASSIGN command facilitates this by allowing you +to display, assign, reassign, or remove the drive letter assignments.

+

Syntax

+

ASSIGN /?
+ASSIGN /L
+ASSIGN <drv>=
+ASSIGN
+ASSIGN [<drv>],...
+ASSIGN <drv>=[<device>:[<slice>]],...
+ASSIGN <tgtdrv>=<srcdrv>,...
+ASSIGN /B='*'<option>'*'['*'<option>'*'['*'<option>'*'...]]

+

Usage

+

ASSIGN /? will display brief command usage and version information.

+

ASSIGN /L will display a list of all the devices available to be used +in drive assignments in the running system. The devices listed may or +may not contain media. Although some device types support the use of +slices, the list does not indicate this.

+

ASSIGN A: just specifying the drive letter will display the assignment +for the drive letter

+

ASSIGN with no parameters will list all of the current drive +assignments.

+

Usage (Specific)

+

The following describes how to assign drive specifically by identifing +each drive by its unique device and slice id’s

+

ASSIGN <drv> will display the assignment for the specific drive +For example, ASSIGN C: will display the assignment for drive C:.

+

ASSIGN <drv>=<device>[:<slice>] will assign (or +reassign) a drive letter to a new device and (optionally) slice. If no +slice is specified, then slice 0 is assumed. For example, +ASSIGN C:=IDE0 will assign drive letter C: to device IDE0, slice 0. +ASSIGN D:=IDE0:3 will assign drive letter D: to device IDE0 slice 3.

+

The ASSIGN command will not allow you to specify a slice (other than +zero) for devices that do not support slices. A slice should only be +specified for hard disk devices (SD, IDE, PPIDE). Floppy disk drives and +RAM/ROM drives do not have slices.

+

ASSIGN <drv>= can be used to remove the assignment from a drive +letter. So, ASSIGN E:= will remove the association of drive letter E: +from any previous device.

+

ASSIGN <tgtdrv>=<srcdrv> is used to swap the assignments of +two drive letters. For example, ASSIGN C:=D: will swap the device +assignments of C: and D:.

+

The ASSIGN command supports “stacking” of instructions. For example, +ASSIGN C:=IDE0:0,D:=IDE0:1,E:= will assign C: and D: to the first two +slices of IDE 0 and will unassign E:.

+

When the command runs it will echo the resultant assignments to the +console to confirm its actions. It will also display the remaining space +available in disk buffers.

+

Usage (Bulk)

+

The following describes how to assign drives in bulk without having to +specify the identifiers of each drive being mapped. Instead bulk mode +has a predefined set options (identified by single letter) which will +map drives. Bulk mode works by assigning drives sequentially starting at +A: until all drives are used, or there are no more options to process. +Each option will typically map between 0 and N drives depending on the +option and the available hardware in your system.

+

ASSIGN /B=<option><option>… will perform bulk assignment .

+

The following options will assign a small number of devices, typically +you would place at beginning of an option list.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionNameDescriptionAssigned
BBootThe boot device1
ARAMRam drive0,1
OROMRom drive0,1
FFloppyAll floppy devices, with/without media0,1,2,..
PPreserveSkip and preserve the next drive assignment1
XExcludeUn-assign / Exclude the next drive1
+

A drive e.g. RAM, ROM, FLOPPY can only be assigned if it exists. if you +system doesn’t have the hardware that supports the device, then no +devices will be assigned, and the next option will be processed.

+

B assigns the boot device. If used the Boot drive should typically +be assigned first.

+

P will not make any changes to the next drive, it will skip over it. +While the X option will un-assign the next drive, leaving a gap.

+

The remaining options will fill drives mostly to end, from hard drive +slices, generally choose 1 of the following:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionNameDescriptionAssigned
SSlicesAssign slices from boot hard drive…max
HHard DriveAssign slices evenly from all hard drives…max
LLegacy HDAssign slices from all hard drives (legacy)6,…max
ZExclude AllUn-assign all remaining drives…max
+

Slices assignment will map all remaining drives to slices from the +boot device. If I have other hard drives present these will not be +mapped by this option.

+

e.g. ASSIGN /B=BAOS

+

Will first assign drives A:(Boot), B:(RAM), C:(ROM) this leaves 13 +drives which will be assigned to slices from the boot hard drive (D: +thru P:), leaving no unused drives.

+

’H’ard drive assignment will attempt to fill all remaining drive letters +by splitting the number of drives remaining evenly across all.

+

e.g. ASSIGN /B=BAOH

+

Will first assign drives A:(Boot), B:(RAM), C:(ROM) this leaves 13 +drives available. If I have 3 hard disks then (13/3) = 4 slices from +each hard drive will be assigned to drives (D: thru O:), leaving a +single unused drive (P:).

+

Legacy hard drive assignment is identical to how the startup hard disk +assignment works. ie. Attempt to assign up to 8 hard drives split across +hard drives detected at boot.

+

e.g. ASSIGN /B=BAOL

+

Will first assign drives A:(Boot), B:(RAM), C:(ROM). If I have 3 hard +disks then (8/3) = 2 slices from each hard drive will be assigned to +drives (D: thru I:), leaving 7 unused drives (J: thru P:).

+

Notes

+

If the ASSIGN command encounters any rule violations or errors, it +will abort with an error and none of the drive assignments will be +implemented. In other words, the command is atomic and will either +completely succeed or completely fail.

+

All assigned drives utilize disk buffer space from a limited pool. The +ASSIGN command will display the amount of buffer space remaining after +an assign command is executed. Buffer space is freed if a drive is +unassigned. If the total assignments exceed the available disk buffer +space available, the command will abort with an error message.

+

The ASSIGN command does not check to see if the device and slice being +assigned actually contains readable media. If the assigned device has no +media, you will receive an I/O error when you attempt to use the drive +letter.

+

The ASSIGN command does not check that the media is large enough to +support the slice you specify. In other words, you could potentially +assign a drive letter to a slice that is beyond the end of the media in +a device. In this case, subsequent attempts to use that drive letter +will result in an I/O error.

+

Additionally, the ASSIGN command does not check to see if the slice +specified refers to an area on your media that is occupied by other data +(such as a FAT filesystem).

+

You will not be allowed to assign multiple drive letters to a single +device and slice. In other words, only one drive letter may refer to a +single filesystem at a time.

+

Attempts to assign a duplicate drive letter will fail and display an +error. If you wish to assign a different drive letter to a +device/unit/slice, unassign the existing drive letter first.

+

Drive letter A: must always be assigned to a device and slice. The +ASSIGN command will enforce this.

+

The changes made by this command are not permanent. The assignments will +persist through a warm start, but when you reboot your system, all drive +letters will return to their default assignments. A SUBMIT batch file +can be used to setup desired drive assignments automatically at boot.

+

Be aware that this command will allow you to reassign or remove the +assignment of your system drive letter. This can cause your operating +system to fail and force you to reboot.

+

The ASSIGN command does not prevent you from assigning a drive +letter to a slice that does not fit on the physical media. However, any +subsequent attempt to refer to that drive letter will result in an +immediate OS error of “no disk”. Refer to “Hard Disk Capacity” in the +RomWBW User +Guide +for a discussion of the exact number of slices that will fit on a +specific physical disk size.

+

This command is particularly sensitive to being matched to the +appropriate version of the RomWBW ROM you are using. Be very careful to +keep all copies of ASSIGN.COM up to date with your ROM.

+

Additionally, the ASSIGN command must be able to adjust to CP/M 2.2 +vs. CP/M 3. If you utilize an RSX that modifies the BDOS version +returned, you are likely to have serious problems. In this case, be sure +to use ASSIGN prior to loading the RSX or after it is unloaded.

+

Etymology

+

The ASSIGN command is an original product and the source code is +provided in the RomWBW distribution.

+

BBCBASIC (BBC BASIC)

+ + + + + + + + + + + + + + + + + +
BBCBASIC
ROM-basedNo
Disk-basedYes
+

BBC BASIC is an interpreted version of the BASIC programming language +originally developed by Acorn Computers for the 6502 CPU. Compared to +other BASIC implementations, BBC BASIC adds structured programming as +well as a built-in Z80 assembler.

+

Syntax

+

BBCBASIC [\<filename>]

+

Usage

+

The full documentation for BBC BASIC (Z80) is found online at +https://www.bbcbasic.co.uk/bbcbasic/mancpm/index.html.

+

Notes

+

The cursor and screen management assumes the use of an ANSI/VT-100 +terminal which is generally correct for RomWBW. Support for a hardware +system timer is also implemented. If your system does not have a +hardware timer, the TIME function will always return 0 and the timeout +parameter of the INKEY(n) function will not be observed (will never +timeout).

+

Etymology

+

This is a RomWBW HBIOS adaptation of BBCBASIC v5.00 by R.T.Russell. This +implementation was adapted from the source code found at +https://github.com/rtrussell/BBCZ80.

+

The adaptation to RomWBW was minimal and includes:

+
    +
  • +

    VT100 terminal control

    +
  • +
  • +

    TIME function

    +
  • +
+

CLRDIR (Clear Directory)

+ + + + + + + + + + + + + + + + + +
CLRDIR
ROM-basedYes
Disk-basedYes
+

The CLRDIR command is used to initialise the directory area of a +drive.

+

Syntax

+

CLRDIR<drv>

+

Usage

+

CLRDIR<drv> will initialise the directory area of the specified +drive. The drive may take any form - eg floppy disk, hard-disk, CF, uSD +etc.

+

The use of FDISK80 to reserve space, or slices, for CP/M use as drives +will not initialise the directory areas of those slices. The resultant +directory areas will contain garbage left over from a previous use of +the disk (or media) and using them in this state with CP/M will very +likely lead to failed or corrupted data storage. Use CLRDIR to +initialise the directory properly.

+

FDU will initialise the directory of a floppy disk as part of the +formatting process and so CLRDIR is unnecessary for a floppy disk. +CLRDIR is, therefore, primarily used with other types such as +hard-disk, CF and uSD.

+

The CLRDIR command may also be used to effectively ‘reformat’ a used +disk by reinitialising its directory area and effectively making it +blank again.

+

Use CLRDIR with caution as changes made to disks by CLRDIR cannot be +undone.

+

Notes

+

If CLRDIR is used on disk containing data then the directory area will +be reinitialised and the data previously stored will be lost.

+

CPUSPD (CPU Speed)

+ + + + + + + + + + + + + + + + + +
CPUSPD
ROM-basedYes
Disk-basedYes
+

The CPUSPD application is used to change the running speed and wait +states of a RomWBW system. It can also be used to invoke a warm or cold +reboot of the system.

+

The functionality is highly dependent on the capabilities of your +system.

+

Syntax

+

CPUSPD [<speed>[,[<memws>][,[<iows>]]]
+CPUSPD (W)armBoot
+CPUSPD (C)oldBoot

+

<speed> is one of (H)alf, (F)ull, (D)ouble, or (Q)uad. <memws> +is a number specifying the desired memory wait states. <iows> is a +number specifying the desired I/O wait states.

+

Usage

+

Entering CPUSPD with no parameters will display the current CPU speed +and wait state information of the running system. Wait state information +is not available for all systems.

+

To modify the running speed of a system, you can specify the +** parameter. To modify either or both of the wait states, +you can enter the desired number. Either or both of the wait state +parameters may be omitted and the current wait state settings will +remain in effect.

+

Notes

+

The ability to modify the running speed and wait states of a system +varies widely depending on the hardware capabilities and the HBIOS +configuration settings.

+

Note that it is frequently impossible to tell if a system is capable of +dynamic speed changes. This function makes the changes blindly. If an +attempt is made to change the speed of a system that is definitely +incapable of doing so, then an error result is returned.

+

Z180-based systems will be able to adjust their CPU speed depending on +the specific variant of the Z180 chip being used:

+ + + + + + + + + + + + + + + + + + + + + +
Z180 VariantCapability
Z80180 (original)Half
Z8S180 Rev. KHalf, Full
Z8S180 Rev. NHalf, Full, Double
+

SBC and MBC systems may be able to change their CPU speed if the +hardware supports it and it is enabled in the HBIOS configuration.

+

The CPUSPD command makes no attempt to ensure that the new CPU speed +will actually work on the current hardware. Setting a CPU speed that +exceeds the capabilities of the system will result in unstable operation +or a system stall.

+

In the case of Z180 CPUs, it is frequently necessary to add memory wait +states when increasing the CPU speed.

+

Some peripherals are dependent on the CPU speed. For example, the Z180 +ASCI baud rate and system timer are derived from the CPU speed. The +CPUSPD application will attempt to adjust these peripherals for correct +operation after modifying the CPU speed. However, in some cases this may +not be possible. The baud rate of ASCI ports have a limited set of +divisors. If there is no satisfactory divisor to retain the existing +baud rate under the new CPU speed, then the baud rate of the ASCI +port(s) will be affected.

+

Etymology

+

The CPUSPD application was custom written for RomWBW. All of the +hardware interface code is specific to RomWBW and the application will +not operate correctly on non-RomWBW systems.

+

The source code is provided in the RomWBW distribution.

+

COPYSL (Copy Slice)

+ + + + + + + + + + + + + + + + + +
COPYSL
ROM-basedNo
Disk-basedYes
+

The purpose of this utility is to allow the copying of whole disk slices +from one disk slice to another slice

+

This tool is only supported by RomWBW HBIOS, it uses HDIOS for all its +disk IO. UNA UBIOS is not supported by this tool.

+

This tool is running on CP/M 2.2 or 3.0 and has access to full 64kb of +RAM, with a minimum of 48kb TPA

+

This tool only works with hard disk devices, other media types like +floppy, are not supported at this time. This tool works across different +hard disk device types, even of different physical type

+

Both hd1k and hd512 are fully supported, however copying from one layout +type to the other is not supported.

+

During operation data is copied in a single read/write pass, data is not +verified by default. If there is a write error, it will be reported, and +operation will stop.

+

Syntax

+

This tool operates at the disk level via RomWBW, thus all disk +identifiers are in the RomWBW \<disk>.\<unit> format.

+

The syntax (similar to copy) for the command is:

+

COPYSL\<destunit>[.\<slice>]=\<srcunit>[.\<slice>] +[/\<options>]

+

E.g.

+

COPYSL 3.3=2.10 /U

+

Means copy from slice 10 on disk 2, onto disk 3 slice 3. This is in +unattended mode, so you will not be asked to confirm the copy operation.

+

Options

+

F - Full disk copy. Copies the complete disk slice, all sectors.
+U - Unattended. Will complete copy without confirmation from the user.
+V - Verify. Does an additional read and verify after write.

+

Usage

+

When run COPYSL will perform command line argument validation and +display an error if they are illegal. Also any disk IO errors will cause +COPYSL to exit.

+

When specifying slice number(s) a check is made that the slice number is +valid, i.e. not too large that it would extend past the end of the +partition (hd1k), or the end of the media (hd512). For hd512 a check is +also performed to ensure that the slice would not extend into the first +defined partition.

+

The copy operation will be faster if the source disk has been formatted +with the CP/M file system, since during copy the CP/M directory is +scanned, and unused blocks are not copied.

+

If a filesystem is not found, (or the /F option is chosen) all data is +copied.

+

Verification (if option chosen) will do an aditional read (after write) +and compare the data read matches what was written. This compare is only +on every 32’nd byte. This is done for efficiency.

+

During copy dots “.” will be displayed to indicate progress of the copy. +Each “.” represents 16 kBytes of data. Each line of “.” ’s is 1 mBytes.

+

Notes

+

This tool has been tested on both SD and CF media types and with hd1k +and hd512 formatted media.

+

You cannot copy slices between different hard disk formats (hd512 and +hd1k) because the slices are incompatible.

+

Etymology

+

The COPYSL application was custom written for RomWBW and contributed +by Mark Pruden.

+

FAT (FAT Utility)

+ + + + + + + + + + + + + + + + + +
FAT
ROM-basedYes
Disk-basedYes
+

The operating systems included with RomWBW do not have any native +ability to access MS-DOS FAT filesystems. The FAT application can be +used overcome this. It will allow you to transfer files between CP/M and +FAT filesystems (wildcards supported). It can also erase files, format, +and list directories of FAT filesystems.

+

Syntax

+

FAT DIR<path>
+FAT COPY<src> <dst>
+FAT REN<from> <to>
+FAT DEL<path>[<file>|<dir>]
+FAT MD<path>
+FAT FORMAT<drv>

+

<path> is a FAT path
+<src>, <dst> are FAT or CP/M filenames
+<from>, <to> are FAT filenames
+<file> is a FAT filename
+<dir> is a FAT directory name
+<drv> is a RomWBW disk unit number

+

CP/M filespec: <d>:FILENAME.EXT (<d> is CP/M drive letter +A-P)
+FAT filespec: <u>:/DIR/FILENAME.EXT (<u> is RomWBW disk unit +#)

+

Usage

+

The FAT application determines whether you are referring to a CP/M +filesystem or a FAT filesystem based on the way you specify the file or +path. If the file or path is prefixed with a number (n:), then it is +assumed this is a FAT filesystem reference and is referring to the FAT +filesystem on RomWBW disk unit ‘n’. Otherwise, the file specification is +assumed to be a normal CP/M file specification.

+

If you wanted to list the directory of the FAT filesystem on RomWBW disk +unit 2, you would use FAT DIR 2:. If you only wanted to see the “.TXT” +files, you would use FAT DIR 2:*.TXT.

+

If you wanted to copy all of the files on CP/M drive B: to the FAT +filesystem on RomWBW disk unit 4, you would use the command +FAT COPY B:*.* 4: If you wanted to copy the files to the “FOO” +directory, then you would use FAT COPY B:*.* 4:\FOO. To copy files in +the opposite direction, you just reverse the parameters.

+

To rename the file “XXX.DAT” to “YYY.DAT” on a FAT filesystem, you could +use a command like “FAT REN 2:XXX.DAT 2:YYY.DAT”.

+

To delete a file “XXX.DAT” on a FAT filesystem in directory “FOO”, you +would use a command like FAT DEL 2:\FOO\XXX.DAT.

+

To make a directory called “FOO2” on a FAT filesystem, you would use a +command line FAT MD 2:\FOO2.

+

To format the filesystem on a FAT partition, you would use a command +like FAT FORMAT 2:. Use this with caution because it will destroy all +data on any pre-existing FAT filesystem on disk unit 2.

+

Notes

+

Partitioned or non-partitioned media is handled automatically. A floppy +drive is a good example of a non-partitioned FAT filesystem and will be +recognized. Larger media will typically have a partition table which +will be recognized by the application to find the FAT filesystem.

+

Although RomWBW-style CP/M media does not know anything about partition +tables, it is entirely possible to have media that has both CP/M and FAT +file systems on it. This is accomplished by creating a FAT filesystem on +the media that starts on a track beyond the last track used by CP/M. +Each CP/M slice can occupy up to 8MB. So, make sure to start your FAT +partition beyond (slice count) * 9MB.

+

The application infers whether you are attempting to reference a FAT or +CP/M filesystem via the drive specifier (char before ‘:’). A numeric +drive character specifies the HBIOS disk unit number for FAT access. An +alpha (A-P) character indicates a CP/M file system access targeting the +specified drive letter. If there is no drive character specified, the +current CP/M filesystem and current CP/M drive is assumed. For example:

+

2:README.TXT refers to FAT file “README.TXT” on disk unit #2
+C:README.TXT refers to CP/M file “README.TXT” on CP/M drive C
+README.TXT refers to CP/M file “README.TXT” on the current CP/M drive

+

Files with SYS, HIDDEN, or R/O only attributes are not given any special +treatment. Such files are found and processed like any other file. +However, any attempt to write to a read-only file will fail and the +application will abort.

+

It is not currently possible to reference CP/M user areas other than the +current user. To copy files to alternate user areas, you must switch to +the desired user number first or use an additional step to copy the file +to the desired user area.

+

Accessing FAT filesystems on a floppy requires the use of RomWBW HBIOS +v2.9.1-pre.13 or greater.

+

Only the first 8 RomWBW disk units (0-7) can be referenced.

+

Files written are not verified.

+

Wildcard matching in FAT filesystems is a bit unusual as implemented by +FatFs. See FatFs documentation.

+

Etymology

+

The FAT application is an original RomWBW work, but utilizes the FsFat +library for all of the FAT filesystem work. This application is written +in C and requires SDCC to compile. As such it is not part of the RomWBW +build process. However, the full project and source code is found in the +FAT GitHub Repository.

+

Known Issues

+

CP/M (and workalike) OSes have significant restrictions on filename +characters. The FAT application will block any attempt to create a file +on the CP/M filesystem containing any of these prohibited characters:

+

< > . , ; : ? * [ ] |/ \

+

The operation will be aborted with “Error: Invalid Path Name” if such +a filename character is encountered.

+

Since MS-DOS does allow some of these characters, you can have issues +when copying files from MS-DOS to CP/M if the MS-DOS filenames use these +characters. Unfortunately, FAT is not yet smart enough to substitute +illegal characters with legal ones. So, you will need to clean the +filenames before trying to copy them to CP/M.

+

The FAT application does try to detect the scenario where you are +copying a file to itself. However, this detection is not perfect and can +corrupt a file if it occurs. Be careful to avoid this.

+

FDISK80

+ + + + + + + + + + + + + + + + + +
FDISK80
ROM-basedYes
Disk-basedYes
+

FDISK80 allows you to create and manage traditional partitions on your +hard disk media. Depending on the hard disk format and features you are +using, RomWBW may need hard disk partitions defined.

+

Please refer to the RomWBW User +Guide +for more information on the use of partitions within RomWBW. It is very +important to understand that RomWBW slices are completely different from +disk partitions.

+

This application is provided by John Coffman. The primary documentation +is in the file “FDisk Manual.pdf” found in the Doc directory of the +RomWBW distribution.

+

Usage

+

FDISK80 is an interactive application. At startup it will ask you for +the disk unit that you want to partition. When your RomWBW system boots, +it will display a table with the disk unit numbers. Use the disk unit +numbers from that table to enter the desired disk unit to partition.

+

FDISK80 operates very much like other FDISK disk partitioning +applications. Please refer to the file called “FDisk Manual.pdf” in the +Doc directory of the RomWBW distribution for further instructions.

+

If ‘slices’ for CP/M have been created using FDISK80, then these will +need to have their directory areas initialised properly using CLRDIR. +Failure to do this will likely result in corrupted data.

+

There is also more information on using FAT partitions with RomWBW in +the RomWBW User +Guide +document in the Doc directory of the distribution.

+

Notes

+

Hard disk partition tables allow a maximum of 1024 cylinders when +defining partitions. However, RomWBW uses exclusively Logical Block +Addressing (LBA) which does not have this limitation. When defining +partitions is usually best to define the start and size of of the +partition using bytes or sectors.

+

Etymology

+

The source for this application was provided directly by John Coffman. +It is a C program and requires a build environment that includes the +SDCC compiler. As such, it is not included in the RomWBW build process, +only the binary executable is included.

+

Please contact John Coffman if you would like a copy of the source.

+

FDU (Floppy Disk Utility)

+ + + + + + + + + + + + + + + + + +
FDU
ROM-basedYes
Disk-basedYes
+

The FDU application is a Floppy Disk Utility that provides functions to +format and test floppy disk media.

+

Syntax

+

FDU

+

Usage

+

This application has an interactive user interface. At startup, you will +be prompted to select the floppy interface hardware in your system. +Following this, you will see the main menu of the program with many +functions to manage floppy disk drives.

+

The primary documentation for this application is in a file called +“FDU.txt” in the Doc directory of the RomWBW distribution. Please +consult this file for usage information.

+

Notes

+

This application interfaces directly to the floppy hardware in your +system. It does not use the RomWBW HBIOS. This means that even if your +system is not configured for floppy drives, you can still use FDU to +test your floppy drives and format floppy media. This also means it is +critical that you choose the correct hardware interface from the initial +selection when starting the application.

+

Etymology

+

The FDU command is an original product and the source code is provided +in the RomWBW distribution.

+

FLASH (Flash EEPROM)

+ + + + + + + + + + + + + + + + + +
FLASH
ROM-basedYes
Disk-basedYes
+

Most of the hardware platforms that run RomWBW support the use of +EEPROMs – Electronically Erasable Programmable ROMs. The FLASH +application can be used to reprogram such ROMS in-situ (in-place), thus +making it possible to upgrade ROMs without a programmer or even removing +the ROM from your system.

+

This application is provided by Will Sowerbutts.

+

Syntax

+

FLASH READ<filename>[options]
+FLASH VERIFY<filename>[options]
+FLASH WRITE<filename>[options]

+

<filename> is the filename of the ROM image file

+

FLASH4 will auto-detect most parameters so additional options should not +normally be required.

+

Options:

+

/V: Enable verbose output (one line per sector)
+/P or /PARTIAL: Allow flashing a large ROM from a smaller image +file
+/ROM: Allow read-only use of unknown chip types
+/Z180DMA: Force Z180 DMA engine
+/UNABIOS: Force UNA BIOS bank switching
+/ROMWBW: Force RomWBW (v2.6+) bank switching
+/ROMWBWOLD: Force RomWBW (v2.5 and earlier) bank switching
+/P112: Force P112 bank switching
+/N8VEMSBC: Force N8VEM SBC (v1, v2), Zeta (v1) SBC bank switching

+

Usage

+

To program your EEPROM ROM chip, first transfer the file to your RomWBW +system. Then use the command FLASH WRITE *`*. The +application will auto-detect the type of EEPROM chip you have, program +it, and verify it.

+

You can use the FLASH READ form of the command to read the ROM image +from your system into a file. This is useful if you want to save a copy +of your current ROM before reprogramming it.

+

Although FLASH WRITE automatically performs a verification, you can +manually perform a verification function with the FLASH VERIFY form of +the command.

+

The author’s documentation for the application is found in the RomWBW +distribution in the Doc/Contrib directory.

+

Notes

+

The application supports a significant number of EEPROM parts. It should +automatically detect your part. If it does not recognize your chip, make +sure that you do not have a write protect jumper set – this jumper can +prevent the ROM chip from being recognized.

+

Reprogramming a ROM chip in-place is inherently dangerous. If anything +goes wrong, you will be left with a non-functional system and no ability +to run the FLASH application again. Use this application with caution +and be prepared to use a hardware ROM programmer to restore your system +if needed.

+

Etymology

+

This application was written and provided by Will Sowerbutts. He +provides it in binary format and is included in the RomWBW distribution +as a binary file.

+

The source code for this application can be found at the FLASH4 GitHub +repository.

+

FORMAT

+ + + + + + + + + + + + + + + + + +
FORMAT
ROM-basedYes
Disk-basedYes
+

This application is just a placeholder for a future version that will +make it simpler to format media including floppy disks.

+

Syntax

+

FORMAT

+

Notes

+

This application currently just displays a few lines of information +briefly instructing a user how to format media. It performs no actual +function beyond this display currently.

+

Etymology

+

The FORMAT command is an original product and the source code is +provided in the RomWBW distribution.

+

HTALK (HBIOS Talk)

+ + + + + + + + + + + + + + + + + +
HTALK
ROM-basedYes
Disk-basedYes
+

HTALK is a variation of the TALK utility, but it works directly +against HBIOS Character Units.

+

Syntax

+

HTALK COMn:

+

Usage

+

HTALK operates at the HBIOS level.

+

The parameter to TALK refers to a HBIOS character unit. Upon execution +all characters typed at the console will be sent to the device specified +and all characters received by the specified device will be echoed on +the console.

+

Press Control+Z on the console to terminate the application.

+

Notes

+

Etymology

+

The TALK command was created and donated to RomWBW by Tom Plano. It is +an original product designed specifically for RomWBW.

+

MODE

+ + + + + + + + + + + + + + + + + +
MODE
ROM-basedYes
Disk-basedYes
+

The MODE command allows you to adjust the operating characteristics such +as baud rate, data bits, stop bits, and parity bits of serial ports +dynamically.

+

Syntax

+

MODE /? +MODE COM<n>: [<baud>[,<parity>[,<databits>[,<stopbits>]]]] [/P]

+

/? displays command usage and version information

+

<n> is the character device unit number

+

<baud> is numerical baudrate

+

<parity> is (N)one, (O)dd, (E)ven, (M)ark, or (S)pace

+

<databits> is number of data bits, typically 7 or 8

+

<stopbits> is number of stop bits, typically 1 or 2

+

/P prompts user prior to setting new configuration

+

Usage

+

MODE /? will display basic command usage and version information.

+

MODE with no parameters will list all devices and their current +configuration.

+

MODE <n> will display the current configuration of the specified +character device unit.

+

MODE COM<n>: [<baud>[,<parity>[,<databits>[, +<stopbits>]]]] [/P] requests that the specified configuration be +set on the character device unit. You can use commas with no values to +leave some values unchanged. As an example, MODE COM0: 9600,,,2 will +setup character device unit 0 for 9600 baud and 2 stop bits while +leaving data bits and stop bits as is.

+

Appending /P in a command specifying a new configuration will cause +the terminal output to pause and wait for the user to press a key. This +allows the user to change the local terminal setup before continuing.

+

Notes

+

Specified baud rate and line characteristics must be supported by the +serial unit. Any parameters not specified will remain unchanged.

+

Changes are not persisted and will revert to system defaults at next +system boot.

+

Not all character devices support all MODE options. Some devices +(notably ASCI devices) have limited baud rate divisors. An attempt to +set a baud rate that the device cannot support will fail with an error +message.

+

Etymology

+

The MODE command is an original product and the source code is +provided in the RomWBW distribution.

+

REBOOT

+ + + + + + + + + + + + + + + + + +
REBOOT
ROM-basedYes
Disk-basedYes
+

The REBOOT application is used to restart a running system from an +operating system prompt. It can invoke either a warm or cold restart via +command line switches.

+

Syntax

+

REBOOT /W
+REBOOT /C
+REBOOT /?

+
    +
  • /C initiates a cold restart
  • +
  • /W initiates a warm restart
  • +
  • /? displays command line usage
  • +
+

Usage

+

Entering REBOOT with no parameters will display the usage and version +information. Use /C or /W to immediately initiate a cold or warm +restart.

+

Notes

+

A warm restart just returns to the Boot Loader menu.

+

A cold restart will reinitialize the system as though power had been +recycled.

+

Etymology

+

The REBOOT application was custom written for RomWBW by MartinR. All +of the hardware interface code is specific to RomWBW and the application +will not operate correctly on non-RomWBW systems.

+

The source code is provided in the RomWBW distribution.

+

RTC (Real Time Clock)

+ + + + + + + + + + + + + + + + + +
RTC
ROM-basedYes
Disk-basedyes
+

Many RomWBW systems provide real time clock hardware. The RTC +application is a simple, interactive program allowing you to display and +set the time and registers of the RTC.

+

Syntax

+

RTC

+

Usage

+

After startup, the application provides the following options:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionFunction
E)xitwill terminate the application.
T)imewill display the time as read from the RTC hardware.
st(A)rtwill restart the clock running if it is stopped.
S)etwill program the RTC clock with the date/time previously entered using the I)nit option.
R)awwill read the minute/second of the RTC clock iteratively every time the space key is pressed. Press enter to end.
L)oopwill read the full date/time of the RTC clock iteratively every time the space key is pressed. Press enter to end.
C)hargewill enable the battery charging function of the RTC.
N)ochargewill disable the battery charging function of the RTC.
D)elayallows you to test the built-in timing delay in the program. It is not unusual for it to be wrong.
I)nitallows you to enter a date/time value for subsequent programming of the RTC using the S)et option.
G)etallows you to read the value of a non-volatile register in the RTC.
P)utallows you to write the value of a non-volatile register in the RTC.
B)ootwill reboot your system.
H)elpdisplays brief help.
+

Notes

+

When using Get and Put options, the register number to read/write is +entered in hex. The non-volatile ram register numbers are 0x20-0x3F.

+

When entering values, you must enter exactly two hex characters. The +backspace key is not supported. You do not use enter after entering the +two hex characters. Yes, this should be improved.

+

The RTC application interacts directly with the RTC hardware bypassing +HBIOS.

+

Etymology

+

The RTC application was originally written by Andrew Lynch as part of +the original ECB SBC board development. It has since been modified to +support most of the hardware variations included with RomWBW.

+

SLABEL (Slice Label)

+ + + + + + + + + + + + + + + + + +
SLABEL
ROM-basedNo
Disk-basedYes
+

Display or change the label of a disk slice.

+

The label applied is only used as informational purposes, displayed by +RomWBW when an OS is booted. It has no correlation with any OS volume +label scheme that may exist. i.e. It does not affect the CP/M 3 disk +label as applied by the SET command

+

Syntax

+

SLABEL [unit.slice=label] [/?]

+

unit.slice the disk unit and slice number to apply the new label to. +This is in the same format as when booting the system to a disk

+

label is the new disk label to apply to the disk

+

Usage

+

SLABEL with no arguments will list All existing labels across All +disks

+

SLABEL 2.5=MYDRIVE will set the disk label of the 6th slice of disk +unit 2

+

SLABEL /? (or other unrecognised parameters) will display a usage +message.

+

Notes

+

There is no capability to update a label onto media that currently does +not have existing media information in the third sector, typically this +means only bootable media.

+

This will only display labels for the first 64 slices of any device. +Slices higher than this are currently ignored.

+

Only bootable RomWBW disk images have a label, which is defined by the +OS which is booted. i.e. NZ-COM has a label of “ZSDOS 1.1” since that is +the booted OS. Prior to RomWBW 3.5 all disk images were defined with the +label “Unlabeled”.

+

Etymology

+

The SLABEL application was custom written for RomWBW and contributed +by Mark Pruden.

+

SURVEY

+ + + + + + + + + + + + + + + + + +
SURVEY
ROM-basedYes
Disk-basedYes
+

The SURVEY command interrogates the system for information on disk +usage, memory usage and I/O ports used, and reports it to the user.

+

Syntax

+

The SURVEY command takes no arguments.

+

SURVEY

+

Usage

+

The results presented by SURVEY include:

+
    +
  1. +

    Information about any drives, within the first eight (ie A: to H:), + which have been logged by the system. This includes: the total + number of files; the storage capacity occupied by those files; and + the capacity remaining on that drive.

    +
  2. +
  3. +

    Information about the the 64KByte CP/M memory map, which is shown + diagramatically, and includes: locations and sizes of the TPA + (Transient Program Area), CP/M’s CCP (Console Command Processor),and + BDOS (Basic Disk Operating System).

    +
  4. +
  5. +

    The addresses of active CPU I/O ports.

    +
  6. +
+

Notes

+

The mechanism by which SURVEY discovers I/O ports is very conservative +and therefore the list returned may not be exhaustive. In particular, it +may fail to discover ports that are ‘write-only’.

+

SYSCOPY (System Copy)

+ + + + + + + + + + + + + + + + + +
SYSCOPY
ROM-basedYes
Disk-basedYes
+

To make disk media bootable, you must write a system boot image onto the +system tracks of the of the media. The SYSCOPY allows you to read or +write the system boot image of disk media.

+

Syntax

+

SYSCOPY<dest>=<src>

+

<dest> is the drive to receive the operating system image or +alternatively a filename to save the operating system image

+

<src> is the drive containing an operating system image or +alternatively a filename containing the system image to be placed on the +destination

+

Usage

+

Both <dest> and <src> can refer to either a drive letter or a +file. If a drive letter is specified, the system boot image will be read +or written to the system tracks of the drive. If a filename is +specified, the system boot image will be read or written to the +specified filename.

+

SYSCOPY C:=ZSYS.SYS will read a system boot image from the file +ZSYS.SYS and write it onto the system tracks of drive C:.

+

SYSCOPY A:OS.SYS=C: will capture the system boot image from the system +tracks of drive C: and store it in the file A:OS.SYS.

+

SYSCOPY D:=C: will copy the system tracks from drive C: onto the +system tracks of drive D:.

+

Notes

+

The RomWBW ROM disk contains files with the system boot image for +Z-System and CP/M 2.2. These files are called CPM.SYS and ZSYS.SYS +respectively. These files can be used as the source of a SYSCOPY +command to make a disk bootable with the corresponding operating system.

+

CP/M 3 uses a two phase boot process. To make a CP/M 3 drive bootable, +you need to put “CPMLDR.SYS” on the boot tracks of the disk and be sure +that the drive also contains the “CPM.SYS” file. The “CPMLDR.SYS” file +is not included on the ROM disk, but is found on the CP/M 3 disk image.

+

ZPM3 is similar to CP/M 3. You also put “CPMLDR.SYS” on the system +tracks of the drive to make it bootable. The ZPM3 operating system is in +the file called “CPM3.SYS” on the ZPM3 disk image. It may seem confusing +that ZPM3 is in the file called CPM3.SYS, but it is normal for ZPM3.

+

For the purposes of booting an operating system, each disk slice is +considered its own operating system. Each slice can be made bootable +with its own system tracks.

+

SYSCOPY uses drive letters to specify where to read/write the system +boot images. However, at startup, the boot loaded will require you to +enter the actual disk device and slice to boot from. So, you need to be +careful to pay attention to the device and slice that is assigned to a +drive letter so you will know what to enter at the boot loader prompt. +By way of explanation, the boot loader does not know about drive letters +because the operating system is not loaded yet.

+

If you want to put a boot system image on a device and slice that is not +currently assigned to a drive letter, you will need to assign a drive +letter first.

+

Not all disk formats include space for system tracks. Such disk formats +cannot contains a system boot image and, therefore, cannot be made +bootable. The best example of such disk formats are the ROM and RAM +disks. To maximize usable file space on these drives, they do not have +system tracks. Obviously, ROM operating system is supported by choosing +a ROM operating system at the boot loader prompt. Any attempt to write a +system boot image to disk media with no system tracks will cause SYSCOPY +to fail with an error message.

+

The system boot images are paired with the ROM version in your system. +So, you must take care to update the system tracks of any bootable disk +when you upgrade your ROM firmware.

+

The system boot images are not tied to specific hardware +configurations. System boot images and operating systems provided with +RomWBW will work with any supported RomWBW platform or hardware as long +as they are the same version as the RomWBW firmware.

+

Etymology

+

The SYSCOPY command is an original product and the source code is +provided in the RomWBW distribution.

+

TALK

+ + + + + + + + + + + + + + + + + +
TALK
ROM-basedYes
Disk-basedYes
+

It is sometimes useful to direct your console input/output to a +designated serial port. For example, if you were to connect a modem to +your second serial port, you might want to connect directly to it and +have everything you type sent to it and everything it sends be shown on +your console. The TALK application does this.

+

Syntax

+

TALK [TTY:|CRT:|BAT:UC1:]

+

Usage

+

TALK operates at the operating system level (not HBIOS).

+

The parameter to TALK refers to logical CP/M serial devices. Upon +execution all characters typed at the console will be sent to the device +specified and all characters received by the specified device will be +echoed on the console.

+

Press Control+Z on the console to terminate the application.

+

Notes

+

This application is designed for CP/M 2.2 or Z-System. Use on later +operating systems such as CP/M 3 is not supported.

+

Etymology

+

The TALK command is an original product and the source code is +provided in the RomWBW distribution.

+

TBASIC (Tasty BASIC)

+ + + + + + + + + + + + + + + + + +
TBASIC
ROM-basedNo
Disk-basedYes
+

Tasty Basic is a basic interpreter for CP/M and RomWBW based on the Z80 +port of Palo Alto Tiny Basic.

+

Syntax

+

TBASIC [\<filename>]

+

Usage

+

Notes

+

Tasty Basic is provided on RomWBW as both a ROM implementation and as a +CP/M application. The CP/M version should be used if you wish to save +Tasty Basic files.

+

Etymology

+

The implementation of Tasty Basic included in RomWBW is the work of +Dimitri Theulings. The primary distribution site for this work is +https://github.com/dimitrit/tastybasic.

+

TIMER

+ + + + + + + + + + + + + + + + + +
TIMER
ROM-basedYes
Disk-basedYes
+

Most RomWBW systems have a 50Hz periodic system timer. A counter is +incremented every time a timer tick occurs. The TIMER application +displays the value of the counter.

+

Syntax

+

TIMER TIMER /? TIMER /C

+

Usage

+

Use TIMER to display the current value of the counter.

+

Use TIMER /C to display the value of the counter continuously.

+

The display of the counter will be something like this:

+

13426 Ticks 268.52 Seconds

+

The first number is the total number of ticks since system startup, +where there are 50 ticks per second. The second number is the total +number of seconds since system startup. Numbers are displayed in decimal +format.

+

Notes

+

The seconds value is displayed with a fractional value which is not a an +actual fraction, but rather the number of ticks past the seconds +rollover. All values are in hex.

+

The primary use of the TIMER application is to test the system timer +functionality of your system.

+

In theory, you could capture the value before and after some process you +want to time.

+

Etymology

+

The TIMER command is an original product and the source code is +provided in the RomWBW distribution.

+

TUNE

+ + + + + + + + + + + + + + + + + +
TUNE
ROM-basedNo
Disk-basedYes
+

If your RomWBW system has a sound card based on either an AY-3-8190 or +YM2149F sound chip, you can use the TUNE application to play PT or MYM +sound files.

+

Note: TUNE will detect an AY-3-8910/YM2149 Sound Module re-gardless of +whether support for it is included in the RomWBW HBIOS configuration

+

Syntax

+

TUNE<filename> **

+

<filename> is the name of a sound file ending in .PT2, .PT3, or .MYM

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionDescription
-MSXForce MSX port addresses A0H/A1H (no PSG detection)
-RCForce RCBus port addresses D8H/D0H (no PSG detection)
--HBIOSUtilise HBIOS’ sound driver
-DELAYForce delay mode (don’t use hardware timer)
+T1Play tune an octave higher
+T2Play tune two octaves higher
-T1Play tune an octave lower
-T2Play tune two octaves lower
+

The +t and -t options apply only to HBIOS mode operation. The -MSX, +-RC, and --HBIOS options are mutually exclusive. See Notes below.

+

Usage

+

The TUNE application supports PT and YM sound file formats. It +determines the format of the file from the extension of the file, so +your tune filenames should end in .PT2, .PT3, or .MYM.

+

To play a sound file, just use the command and specify the file to play +after the command. So, for example, TUNE ATTACK.PT2 will immediately +begin playing the PT sound file “ATTACK.PT2”.

+

Notes

+

The TUNE application automatically probes for compatible hardware at +well known port addresses at startup. It will auto-configure itself for +the hardware found. If no hardware is detected, it will abort with an +error message.

+

Some hardware (notably Why-Em-Ulator) cannot be detected due limitations +of the emulation. In such cases, you can force the use of the two most +common port addresses using the -MSX or -RC options.

+

On Z180 systems, I/O wait states are added when writing to the sound +chip to avoid exceeding its speed limitations. On Z80 systems, you will +need to ensure that the CPU clock speed of your system does not exceed +the timing limitations of your sound chip.

+

The application probes for an active system timer and uses it to +accurately pace the sound file playback. If no system timer is +available, a delay loop is calculated instead. The delay loop will not +be as accurate as the system timer. If the -DELAY options is specified +on the command line, then the delay loop will be used regardless of +whether the system has a hardware timer. This is useful if the hardware +timer does not run at the 50Hz desired for sound playback.

+

There are two modes of operation. A direct hardware interface for the +AY-3-8910 or YM2149 chips, or a compatibility layer thru HBIOS +supporting both the AY-3-8910 and the SN76489 chip.

+

By default the application will attempt to interface directly to the +sound chip. The optional argument --HBIOS supplied after the filename, +will enable the application to use the HBIOS sound driver.

+

The following summarizes the different modes of operation for the +application:

+
    +
  • +

    If you use TUNE with no options, it will use it’s original behavior + of searching for and detecting a sound chip. TUNE will play sound + files directly to the PSG hardware. In this mode it does not matter if + HBIOS does or does not know about the sound chip.

    +
  • +
  • +

    If you use TUNE with the --HBIOS option, it will not detect a + sound chip and will use the RomWBW HBIOS interface. This will only + work if HBIOS was configured for the installed sound card and HBIOS + detects the sound chip.

    +
  • +
  • +

    If you use TUNE with -RC or -MSX, it will play tunes directly to + the PSG hardware (not via HBIOS) and will bypass detection. In this + mode it does not matter if HBIOS does or does not know about the sound + chip.

    +
  • +
+

Note that the HBIOS API for sound cards is pretty good, but does not +implement everything that the sound card can do. For best fidelity, use +TUNE without the --HBIOS option.

+

All RomWBW operating system boot disks include a selection of sound +files in user area 3.

+

Etymology

+

The TUNE application was custom written for RomWBW. All of the +hardware interface code is specific to RomWBW. The sound file decoding +software was adapted and embedded from pre-existing sources. The YM +player code is from MYMPLAY 0.4 by Lieves!Tuore and the PT player code +is (c)2004-2007 S.V.Bulba vorobey@mail.khstu.ru.

+

The source code is provided in the RomWBW distribution.

+

VGMPLAY (Video Game Music Play)

+ + + + + + + + + + + + + + + + + +
VGMPLAY
ROM-basedNo
Disk-basedYes
+

This application will allow you to play Video Game Music files. VGM +files contain music samples from a range of different sound chips that +were used in arcade games, game consoles and personal computer systems.

+

Video Game Music files have a .VGM file extension and each file contains +an embedded header that identifies the hardware it is intended for and +also the title of the music.

+

All RomWBW operating system boot disks include a selection of sound +files in user area 3. Additional music files can be found at:

+

VGMRIPS website

+

PROJECT2612 website

+

Sound files are loaded into memory for playback, so the maximum size +file that can be played is around 52Kb.

+

Sound chips currently supported are:

+
    +
  • AY-3-8190 (and equivalent YM2149)
  • +
  • YM2612 (and equivalent YM3848)
  • +
  • SN76489 (single chip mono and dual chip stereo)
  • +
  • YM2151
  • +
+

VGMPLAY supports playback of files with multiple combinations of these +chips.

+

Syntax

+

VGMPLAY<filename>

+

<filename> is the name of a sound file ending in .VGM

+

Usage

+

VGMPLAY does not automatically detect the hardware platform or sound +hardware that you are using. This means a version customized for your +system must be assembled before use. However, the version as distributed +will work with ECB bus SBC systems.

+

To play a sound file, just use the VGMPLAY command and specify the file +to play after the command. So, for example, VGMPLAY TEDDY will load +the TEDDY.VGM sound file into memory and begin playing it.

+

Playback can be stopped by pressing a key. There may be a delay before +playback stops.

+

Notes

+

The default build configuration for VGMPLAY is:

+

CPU speed: Autodetected

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
chipnumberportnotes
AY-3-89101st09ahstereo
AY-3-89102ndnot setstereo
YM26121st0c0hstereo
YM26122nd0c4hstereo
SN764891st0c8hmono/left
SN764892nd0c9hmono/right
YM21511st0cahstereo
YM21512nd0cbhstereo
+

Inconsistant, garbled or distorted playback can be an indication that +your CPU clock speed is too high for your sound chip. In this case, if +your platform supports speed switching, then the CPUSPD application can +be used to reduce your processor speed.

+

VGMPLAY is still under development. The source code is provided in the +RomWBW distribution.

+

WDATE (WBW DATE)

+ + + + + + + + + + + + + + + + + +
WDATE
ROM-basedNo
Disk-basedYes
+

wdate is a utility for CP/M systems that have Wayne Warthen’s RomWBW +firmware. It reads or sets the real-time clock, using function calls in +the BIOS. It should work on any RTC device that is supported by RomWBW, +including the internal interrupt-driven timer that is is available on +some systems.

+

wdate differs from the rtc.com utility that is provided with the +RomWBW version of CP/M in that it only gets and sets the date/time. +rtc.com can also manipulate the nonvolatile RAM in certain clock +devices, and modify the charge controller. However, wdate is (I would +argue) easier to use, as it takes its input from the command line, which +can be edited, and it’s less fussy about the format. It doesn’t require +the date to be set if you only want to change the time, for example. In +addition, wdate has at least some error checking.

+

wdate displays the day-of-week and month as English text, not numbers. +It calculates the day-of-week from the year, month, and day. RTC chips +usually store a day-of-week value, but it’s useless in this application +for two reasons: first, the BIOS does not expose it. Second, there is no +universally-accepted way to interpret it (which day does the week start +on? Is ‘0’ a valid day of the week?)

+

Syntax

+

WDATE
+WDATE <hr> <min>
+WDATE <hr> <min> <sec>
+WDATE <year> <month> <day> <hr> <min> <sec>

+

Usage

+
A> wdate
+Saturday 27 May 13:14:39 2023
+
+

With no arguments, displays the current date and time.

+
A> wdate hr min
+
+

With two arguments, sets the time in hours and minutes, without changing +date or seconds

+
A> wdate hr min sec
+
+

With three arguments, sets the time in hours, minutes, and seconds, +without changing date

+
A> wdate year month day hr min sec
+
+

With six arguments, sets date and time. All numbers are one or two +digits. The two-digit year starts at 2000.

+
A> wdate /?
+
+

Show a summary of the command-line usage.

+

Notes

+

I’ve tested this utility with the DS1302 clock board designed by Ed +Brindly, and on the interrupt-driven timer built into my Z180 board. +However, it does not interact with hardware, only BIOS; I would expect +it to work with other hardware.

+

wdate checks for the non-existence of RomWBW, and also for failing +operations on the RTC. It will display the terse “No RTC” message in +both cases.

+

The RomWBW functions that manipulate the date and time operate on BCD +numbers, as RTC chips themselves usually do. wdate works in decimal, so +that it can check that the user input makes sense. A substantial part of +the program’s code is taken up by number format conversion and range +checking.

+

Etymology

+

The WDATE application was written and contributed by Kevin Boone. The +source code is available on GitHub at +https://github.com/kevinboone/wdate-cpm.

+

XM (X-Modem)

+ + + + + + + + + + + + + + + + + +
XM
ROM-basedYes
Disk-basedYes
+

An adaptation of Ward Christensen’s X-Modem protocol for transferring +files between systems using a serial port.

+

Syntax

+

XM S<filename>
+XM SK<filename>
+XM L<library> <filename>
+XM LK<library> <filename>
+XM R<filename>

+

The following may be added to the action codes: | S: Send a file | +L: Send a file from a library | R: Receive a file | K: Use 1K +blocksize (send operations) | C: Force use of checksum (receive +operations) | X: Force 128-byte protocol (receive operations) | +0-9: Specifies HBIOS character unit for transfers

+

<filename> is the name of a file to send or receive

+

<library> is the name of a library (.lbr) to extract a file to send

+

For example, the following command will receive a file using checksums +on HBIOS character unit 3 and will name the received file MYFILE.TXT.

+

XM RC3 MYFILE.TXT

+

Usage

+

To transfer a file from your host computer to your RomWBW computer, do +the following:

+
    +
  1. +

    Enter one of the XM receive commands specifying the name you want + to give to the received file.

    +
  2. +
  3. +

    On your host computer select a file to send and initiate the XModem + send operation.

    +
  4. +
+

To transfer a file from your RomWBW computer to your host computer, do +the following:

+
    +
  1. +

    Enter one of the XM send commands specifying the name of the file + to be sent.

    +
  2. +
  3. +

    On your host computer, specify the name to assign to the received + file and initiate and XModem receive operation.

    +
  4. +
+

Please refer to the documentation of your host computer’s terminal +emulation software for specific instructions on how to use XModem.

+

Notes

+

The XModem adaptation that comes with RomWBW will default to using the +current HBIOS console port for transfers. Note that if you change your +console port at the OS level (e.g., STAT CON:=UC1:), this does not +change the HBIOS console.

+

XM attempts to determine the best way to drive the serial port based +on your hardware configuration. When possible, it will bypass the HBIOS +for faster operation. However, in many cases, it will use HBIOS so that +flow control can be used.

+

XM is dependent on a reliable communications channel. You must ensure +that the serial port can be serviced fast enough by either using a baud +rate that is low enough or ensuring that hardware flow control is fully +functional (end to end).

+

Etymology

+

The XM application provided in RomWBW is an adaptation of a +pre-existing XModem application. Based on the source code comments, it +was originally adapted from Ward Christensen’s MODEM2 by Keith Petersen +and is labeled version 12.5.

+

The original source of the application was found on the Walnut Creek +CD-ROM and is called XMDM125.ARK dated 7/15/86.

+

The actual application is virtually untouched in the RomWBW adaptation. +The majority of the work was in the modem driver which was enhanced to +detect the hardware being used and dynamically choose the appropriate +driver.

+

The source code is provided in the RomWBW distribution.

+

ZMD (Z-Modem)

+ + + + + + + + + + + + + + + + + +
ZMD
ROM-basedNo
Disk-basedYes
+

An adaptation of Robert Kramer’s Remote CP/M File Transfer Program with +support for XModem and YModem transfers.

+

NOTE: ZMD does not do ZModem transfers. The Z in ZMD refers to +Z-System compatibility.

+

Syntax

+

ZMD \<mode>\<protocol>\<unit> [\<filename>]

+

where \<mode> can be:
+S - Send file from BBS
+SP - Send from private area
+A - Send ARK/ARC/LBR member
+R - Receive file from YOU
+RP - Receive in private area
+RW - Receive without description(s)
+F - Displays available upload space

+

\<protocol> can be:
+X - Xmodem 128 byte blocks (CRC)
+C - Xmodem 128 byte blocks (Checksum)
+K - Ymodem 1024 byte blocks (CRC only)

+

and \<unit> can specify a single digit (0-9) that specifies the +RomWBW Character Unit to use for the file transfer.

+

Usage

+

To transfer a file from your host computer to your RomWBW computer, do +the following:

+
    +
  1. +

    Enter one of the ZMD receive commands specifying the name you want + to give to the received file (no filename required for ZModem + transfers).

    +
  2. +
  3. +

    On your host computer select a file to send and initiate an XModem + or YModem send operation.

    +
  4. +
+

To transfer a file from your RomWBW computer to your host computer, do +the following:

+
    +
  1. +

    Enter one of the ZMD send commands specifying the name of the file + to be sent.

    +
  2. +
  3. +

    On your host computer, specify the name to assign to the received + file and initiate an XModem or YModem receive operation.

    +
  4. +
+

Please refer to the documentation of your host computer’s terminal +emulation software for specific instructions on how to use XModem.

+

Notes

+

The ZMP adaptation that comes with RomWBW will default to using the +current HBIOS console port for transfers. Note that if you change your +console port at the OS level (e.g., STAT CON:=UC1:), this does not +change the HBIOS console.

+

ZMP attempts to determine the best way to drive the serial port based +on your hardware configuration. When possible, it will bypass the HBIOS +for faster operation. However, in many cases, it will use HBIOS so that +flow control can be used.

+

ZMP is dependent on a reliable communications channel. You must ensure +that the serial port can be serviced fast enough by either using a baud +rate that is low enough or ensuring that hardware flow control is fully +functional (end to end).

+

Etymology

+

ZMD v1.50 was produced by Robert Kramer. The RomWBW adaptation just uses +the RomWBW HBIOS serial API.

+

ZMP (Z-Modem Program)

+ + + + + + + + + + + + + + + + + +
ZMP
ROM-basedNo
Disk-basedYes
+

ZMP is a terminal program for interacting with a modem attached to +your system. It includes X/Y/ZModem file transfer protocols. An actual +modem is not required, but you must have a port for ZMP to use that is +independent of the console running ZMP.

+

Syntax

+

ZMD [\<unit>]

+

\<unit> can specify a single digit (0-9) indicating the RomWBW +Character Unit to use for the modem port.

+

Usage

+

Refer to the file ZMP.DOC found on all disk images that include the +ZMP application.

+

Notes

+

ZMP requires access to multiple overlay and configuration files to +run. It will look for these on the default driver and user area. +Depending the operating system used, you may be able to set up a search +path and locate these files in other locations. The files used by ZMP +are:

+
    +
  • ZMP.HLP
  • +
  • ZMP.DOC
  • +
  • ZMP.CFG
  • +
  • ZMP.FON
  • +
  • ZMXFER.OVR
  • +
  • ZMTERM.OVR
  • +
  • ZMINIT.OVR
  • +
  • ZMCONFIG.OVR
  • +
+

The ZMP console is always the active OS console. If no \<unit> is +specified on the command line, ZMP will default to using HBIOS +Character Unit 1 as the modem port. Take care to avoid using the same +HBIOS Character Unit as both the console and the modem or various +strangeness will occur.

+

ZMP is a full screen application and is configured to use ANSI/VT-100 +screen control.

+

ZMP does not support the range of port configurations provided by +RomWBW. The RomWBW adaptation of ZMP ignores the port configuration +options within ZMP. Instead, you should configure the HBIOS Character +Unit using the RomWBW MODE command before launching ZMP.

+

ZMP is written in C. As a result, file transfers will be noticeably +slower than other assembly language file transfer tools.

+

Etymology

+

ZMP was produced by Ron Murray and was based on HMODEM II. Wayne +Hortensius updated the source to compile with the latest version of +Hi-Tech C and implemented a few enhancements.

+

The RomWBW overlay was developed by Phil Summers.

+
+
+ + + + + + + + + + + diff --git a/Catalog/index.html b/Catalog/index.html new file mode 100644 index 00000000..0b06f1c0 --- /dev/null +++ b/Catalog/index.html @@ -0,0 +1,3986 @@ + + + + + + + + + + + Catalog - RomWBW Documentation V3.6 + + + + + + + + + + + + + + + + +
+
+ +
+ +

RomWBW Disk Catalog \ +Version 3.6 \ +Mark Pruden \& Mykl Orders () \ +30 May 2025

+

RomWBW Distribution File Catalog

+

This document is a reference to the files found on the disk media +distributed with RomWBW. Specifically, RomWBW provides a set of floppy +and hard disk images in the Binary directory of the distribution. The +contents of these images is listed here.

+

The files on the disk images were sourced from a variety of locations. +The primary sources of these files are listed below. Note that the +primary documentation for each of these sources is listed. You are +strongly encouraged to refer to this documentation for more information +on using the applications and files listed.

+

This document primarily describes to contents of the hard disk images. +Floppy disk images may contain a cut down (sub-set) of the files on a +hard disk. This is of course to conserve disk space

+

Note: This document received a major update in October 2024, when while +still not fully complete, most of the core operating system disks should +now be fully described.

+

Sources

+
    +
  • RomWBW: RomWBW Custom Applications
  • +
+

Documentation: RomWBW Applications.pdf

+

These files are custom applications built exclusively to enhance the + functionality of RomWBW. In some cases they are built from scratch + while others are customized versions of well known CP/M tools.

+
    +
  • CPM22: Digital Research CP/M-80 2.2 Distribution Files
  • +
+

Documentation: CPM Manual.pdf

+

These files are from the official Digital Research distribution of + CP/M 2.2. Applications have been patched according to the DRI patch + list.

+
    +
  • ZSDOS: ZSDOS 1.1 Disk Operating System Distribution Files
  • +
+

Documentation: ZSDOS Manual.pdf

+

These files are from the official ZSDOS 1.1 distribution. Some of the + files are redistributions of applications from other sources.

+
    +
  • ZCPR: ZCPR 1.0 Command Processor Distribution Files
  • +
+

Documentation: ZCPR Manual.pdf

+

These files are from the ZCPR 1.0 distribution.

+
    +
  • NZCOM: NZCOM Automatic Z-System Distribution Files
  • +
+

Documentation: NZCOM Users Manual.pdf

+

These files are from the last official release of NZCOM.

+
    +
  • CPM3: Digital Research CP/M 3 Distribution Files
  • +
+

Documentation: CPM3 Users Guide.pdf, CPM3 System Guide.pdf, CPM3 + Programmers Guide.pdf, CPM3 Command Summary.pdf

+

These files are from the official Digital Research distribution of + CP/M 3. Applications have been patched according to the DRI patch + list.

+
    +
  • ZPM3: Digital Research CP/M-80 2.2 Distribution Files
  • +
+

Documentation: CPM Manual.pdf

+

These files are from Simeon Cran’s ZPM3 operating system distribution.

+

Operating System Boot Disks

+

RomWBW contains several ready-to-run disks, that have been adapted for +RomWBW. Theses disks are bootable as is (the operating system image is +already embedded in the system tracks) and can be launched from the +RomWBW Loader prompt.

+

Each Disk contains the following file

+ + + + + + + + + + + + + +
FileDescription
README.TXTInformation about the Operating System
+

CP/M 2.2

+

A vanilla distribution of DRI’s CP/M-80 2.2 adapted for RomWBW.

+

Floppy Disk Image: fd_cpm22.img
+Hard Disk Image: hd_cpm22.img
+Combo Disk Image: Slice 0

+

CP/M 2.2 OS Files

+

These are built and provide the OS. CP/M 2.2 Typically has no boot files +stored on the disk. It entirely boots from the system track

+

The following files appear in User Area 0

+ + + + + + + + + + + + + + + +
FileSourceDescription
CPM.SYSRomWBWDRI CPM 2.2 Boot Image for SYSCOPY
+

CP/M 2.2 Files

+

The following CP/M 2.2 files were distributed by DRI with the operating +system or as supplemental add-on programs. They are documented in the +“CP/M Manual.pdf” document in the Doc/CPM directory of the Rom WBW +distribution.

+

The following files appear in User Area 0

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileDescription
ASM.COMDRI 8080 assembler
DDT.COM8080 dynamic debugger
DUMP.COMDRI type contents of file in hex
ED.COMDRI line editor
HELP.COMCP/M 3 derived HELP display
HELP.HLPCP/M 3 derived HELP data file
LIB.COMDRI object file library manager
LINK.COMDRI object file linker
LOAD.COMDRI loader for Intel hex files
MAC.COMDRI 8080 macro assembler
PIP.COMDRI periperal interchange program
RMAC.COMDRI 8080 relocating macro assembler
STAT.COMDRI file/disk/device info & config
SUBMIT.COMDRI batch file submission tool
XREF.COMDRI assembler cross reference listing utility
XSUB.COMDRI batch file resident extension
ZSID.COMDRI Z80 symbolic debugger
+

NOTE: The above files are also included in the NZCOM disk image.

+

MAC, RMAC, XREF, and ZSID are supplemental programs from DRI with +separate standalone documentation which is not included in the RomWBW +package (but easily found on the Internet via Google search).

+

Additional Files

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileDocumentationUser Area
OS General Files0
General Purpose Applications0
Testing Applications2
Sample Audio Files3
CP/NET 1.24
SIMH Simulator13
+

ZSDOS 1.1

+

It contains a customized version of ZSDOS 1.1 for RomWBW. The disk is +bootable as is (the operating system image is already embedded in the +system tracks) and can be launched from the RomWBW Loader prompt.

+

The starting point for the disk content was the final public release of +ZSDOS which is generally available on the Internet.

+

Floppy Disk Image: fd_zsdos.img
+Hard Disk Image: hd_zsdos.img
+Combo Disk Image: Slice 1

+

ZSDOS 1.1 OS Files

+

These are built and provide the OS. ZSDOS Typically has no boot files +stored on the disk. It entirely boots from the system track

+

The following files appear in User Area 0

+ + + + + + + + + + + + + + + +
FileSourceDescription
ZSYS.SYSRomWBWZSDOS Boot Image for SYSCOPY
+

ZSDOS 1.1 Files

+

The following files came from the official ZSDOS distribution. These are +generally documented in the “ZSDOS Manual.pdf” document in the Doc/CPM +directory of the RomWBW distribution.

+

Note: Some of the files included in the ZSDOS distribution are not +listed below because they have been superseded by more recent versions +listed in other sections below.

+

The following files appear in User Area 0

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileDescription
BGPATCH.HEXPatches BackGrounder II for ZSDOS 1.1 compatibility
CLOCKS.DATLibrary of clock drivers
COPY.UPDDocument describing updates to COPY program
DATSWEEP.COMComprehensive file management w/ date stamp awareness
DSCONFIG.COMProgram to configure DATSWEEP
FA16.CFGZCNFG configuration file for FILEATTR.COM
FA16.DOCDocumentation for FILEATTR.COM
FA16A.FORSummary Information for FILEATTR.COM
FA16CFG.TXTdescribes configuration options for FILEATTR.COM
FILEATTR.COMSet and/or display file attributes
FILEDATE.COMDate/time stamping aware disk directory utility
FILEDATE.CFGZCNFG configuration fie for FILEDATE
INITDIR.COMPrepare disk for P2DOS date/time stamping
INITDIR.CFGZCNFG configuration file for INITDIR
LDDS.COMLoad DateStamper date/time stamping resident extension
LDNZT.COMLoad NZT date/time stamping resident extension
LDP2D.COMLoad P2DOS date/time stamping resident extension
PUTBG.COMUpdated replacement for BackGrounder II PUTBG program
PUTDS.COMPrepare disk for datestamper date/time stamping
RELOG.COMClear fixed disk login vector in ZSDOS
SETTERM.COMTerminal configuration utility for DATSWEEP & DSCONFIG
SETUPZST.COMCreates date/time stamping resident extensions
STAMPS.DATLibrary of date/time stamping modules for SETUPZST
TD.COMRead and set system real-time clock
TD.CFGZCNFG Configuration file for TD.COM
TERMBASE.DATLibrary of terminals used by SETTERM
TESTCLOK.COMTest a selected clock driver
ZCAL.COMDisplay a small one-month calendar to the screen
ZPATH.COMSet or display ZSDOS and ZCPR search paths
ZSCONFIG.COMConfigure features of ZSDOS operating systems
ZSVSTAMP.COMPreserves file date/time stamp across modifications
ZSVSTAMP.DOCDocument describes the use and operation of ZSVSTAMP
+

NOTE: The above files are also included in the NZ-COM disk image +distribution

+

Additional Files

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DocumentationUser Area
CP/M 2.2 Files0
OS General Files0
General Purpose Applications0
Testing Applications2
Sample Audio Files3
SIMH Simulator13
+

NZCOM

+

This disk contains NZ-COM, which is an implementation of the Z-System. +You may also see NZ-COM referred to as ZCPR 3.4. This is a powerful +replacement for CP/M 2.2 w/ full backward compatibility. NZ-COM is +extremely configurable and far more powerful than DRI CP/M. It is almost +mandatory that you read the NZ-COM manual to use the system effectively.

+

Floppy Disk Image: fd_nzcom.img
+Hard Disk Image: hd_nzcom.img
+Combo Disk Image: Slice 2

+

NZ-COM OS Files

+

NZ-COM is not designed to load directly from the boot tracks of a disk. +Instead, it expects to be loaded from an already running OS.

+

This disk has been configured to boot using ZSDOS with a PROFILE.SUB +command file that automatically loads NZ-COM. So, NZ-COM will load +completely without any intervention, but you may notice that ZSDOS loads +first, then ZSDOS loads NZ-COM.

+

The following files appear in User Area 0

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileSourceDescription
!(C)1988NZCOMOriginal copyright (since placed in public domain)
!NZ-COMNZCOMSoftware marker directory entry (empty file)
!VERS--1.2HNZCOMVersion marker directory entry (empty file)
NZCOM.COMNZCOMLoads and launches NZ-COM system
NZCOM.ENVRomWBWZ-System environment descriptor
NZCOM.LBRNZCOMLibrary of NZCOM system modules
NZCOM.ZCMRomWBWEnvironment descriptor (alternate format)
NZCPR.LBRNZCOMLibrary of alternative ZCPR modules
PROFILE.SUBRomWBWCommand file to auto-start NZ-COM at system boot
RCP.LBRNZCOMLibrary of alternative RCP modules
STARTZCM.COMRomWBWCommands to execute after NZ-COM is launched
ZRDOS.ZRLZRDOSRelocatable version of ZRDOS BDOS module
ZSDOS.ZRLZSDOSRelocatable version of ZSDOS 1.1 BDOS module
ZSYS.SYSRomWBWZSDOS Boot Image for SYSCOPY
+

NZ-COM Files

+

The following files came from the official NZ-COM distribution. These +are generally documented in the “NZCOM Users Manual.pdf” document in the +Doc/CPM directory of the RomWBW distribution.

+

NOTE: It may appear theat there are not many files, this is because most +of the OS files are shared with Z3PLUS. See here for a list NZ-COM +Z3PLUS OS Files

+

The following file are in User Area 15, and where noted 10 for help +files, or 14 for config files.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileDescription
ALIAS.CMDSample alias definitions for use with ARUNZ
BGZRDS19.LBRPatch for Backgrounder II (U10)
CMDRUN.COMExtended Command Processor (copied from ARUNZ)
MKZCM.COMCreate/update NZ-COM load environment
NZBLITZ.COMRapid coldboot of complete NZ-COM system image
NZBLTZ14.CFGZCNFG configuration file for NZBLITZ. (U14)
NZBLTZ14.HZPHelp file for NZBLITZ (U10)
NZ-DBASE.INFdBase II application note regarding SUBMIT files (U10)
PUBLIC.COMSpecify ZRDOS public directories/user areas
RELEASE.NOTUpdate information on NZ-COM (U10)
SUB.COMEnhanced version of SUBMIT
+

Additional Files

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DocumentationUser Area
Testing Applications2
Sample Audio Files3
CP/NET 1.24
SIMH Simulator13
CP/M 2.2 Files15
ZSDOS 1.1 Files15, 14, 10
NZ-COM Z3PLUS OS Files15, 14, 10
OS General Files15, 14, 10
General Purpose Applications15, 10
+

CP/M 3

+

A vanilla distribution of DRI’s CP/M 3, also known as CP/M Plus adapted +for RomWBW.

+

Floppy Disk Image: fd_cpm3.img
+Hard Disk Image: hd_cpm3.img
+Combo Disk Image: Slice 3

+

CP/M 3 OS Files

+

The following files appear in User Area 0

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileSourceDescription
BDOS3.SPRCPM3DRI CPM+ GENCPM input file for the non-banked BDOS
BIOS3.SPRRomWBWDRI CPM+ GENCPM input file for non-banked BIOS
BNKBIOS3.SPRRomWBWDRI CPM+ GENCPM input file for banked BIOS
BNKBDOS3.SPRCPM3DRI CPM+ GENCPM input file for banked BDOS
CCP.COMCPM3DRI CPM+ Console Command Processor
CPM3.SYSRomWBWDRI CPM+ (non-banked) memory image
CPM3RES.SYSRomWBWDRI CPM+ (non-banked) memory image
CPM3BNK.SYSRomWBWDRI CPM+ (banked) memory image
CPM3FIX.PATCPM3DRI CPM+ patch list
CPMLDR.COMRomWBWDRI CPM 3.0 Boot Loader Application
CPMLDR.SYSRomWBWDRI CPM 3.0 Boot Loader for SYSCOPY
GENBNK.DATRomWBWGENCPM config data file (banked)
GENRES.DATRomWBWGENCPM config data file (non-banked)
GENCPM.DATRomWBWCurrent GENCPM config data file
GENCPM.COMCPM3DRI CPM+ Create a memory image of CPM3.SYS
RESBDOS3.SPRCPM3DRI CPM+ GENCPM input file for resident BDOS
+

CP/M 3 Files

+

The following CP/M 3 files were distributed by DRI with the operating +system or as supplemental add-on programs. They are documented in the +“CPM3 Command Summary.pdf” document in the Doc/CPM directory of the Rom +WBW distribution.

+

The following files appear in User Area 0

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileDescription
DATE.COMDRI CPM+ Set or display the date and time
DEVICE.COMDRI CPM+ Assign logical devices with one or more physical devices
DIR.COMDRI CPM+ DIR with options
DUMP.COMDRI type contents of disk file in hex
ED.COMDRI CPM+ line editor
ERASE.COMDRI CPM+ file deletion
GENCOM.COMDRI CPM+ Generate special COM file with attached RSX files
GET.COMDRI CPM+ Temporarily get console input form a disk file
HELP.COMDRI CPM+ Display information on how to use commands
HELP.HLPDRI CPM+ Databse of help information for HELP.COM
HEXCOM.COMDRI CPM+ Create a COM file from a hex file (replaces LOAD.COM)
INITDIR.COMDRI CPM+ Initializes a disk to allow time and date stamping
LIB.COMDRI object file library manager
LINK.COMDRI object file linker
MAC.COMDRI 8080 macro assembler
PATCH.COMDRI CPM+ Display or install patch to the CPM+ system or command files
PIP.COMDRI CPM+ Periperal Interchange Program
PUT.COMDIR CPM+ Temporarily redirect printer or console output to a disk file
RENAME.COMDRI CPM+ Rename a file
RMAC.COMDRI 8080 relocating macro assembler
SAVE.COMDRI CPM+ Copy the contents of memory to a file
SET.COMDIR CPM+ Set file options
SETDEF.COMDIR CPM+ Set system options including the drive search chain
SHOW.COMDIR CPM+ Display disk and drive statistics
SUBMIT.COMDRI CPM+ batch processor
TYPE.COMDRI CPM+ Display the contents of an ASCII character file
XREF.COMDRI assembler cross reference listing utility
ZSID.COMDRI Z80 symbolic instruction debugger
+

NOTE: The above files are also included in the ZPM3 and Z3PLUS disk +images.

+

ZSID is a supplemental program from DRI with separate standalone +documentation which is not included in the RomWBW package (but easily +found on the Internet via Google search).

+

Additional Files

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DocumentationUser Area
OS General Files0
General Purpose Applications0
Testing Applications2
Sample Audio Files3
CP/NET 1.24
SIMH Simulator13
+

Z3PLUS

+

Z3PLUS OS Files

+

Z3PLUS is not designed to load directly from the boot tracks of a disk. +Instead, it expects to be loaded from an already running OS.

+

This disk has been configured to boot using CP/M 3 with a PROFILE.SUB +command file that automatically loads Z3PLUS. So, Z3PLUS will load +completely without any intervention, but you may notice that CP/M 3 +loads first.

+

The following Z3PLUS files appear in User Area 0

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileSourceDescription
!(C)1988Z3PLUSOriginal copyright (since placed in public domain)
!VERS--1.02FZ3PLUSVersion marker directory entry (empty file)
!Z3PLUSZ3PLUSSoftware marker directory entry (empty file)
NAMES.NDRRomWBWDefault Directory Names loaded at boot
RCP.LBRZ3PLUSLibrary of alternative RCP modules
PROFILE.SUBRomWBWCommand file to auto-start Z3PLUS at system boot
STARTZ3P.COMRomWBWCommands to execute after Z3PLUS is launched
Z3PLUS.COMZ3PLUSLoads and launches Z3PLUS system
Z3PLUS.LBRZ3PLUSLibrary of Z3PLUS system modules
+

Z3PLUS Files

+

The following files came from the official Z3PLUS distribution. These +are generally documented in the “Z3PLUS Users Manual.pdf” document in +the Doc/CPM directory of the RomWBW distribution. Note:

+

NOTE: It may appear theat there are not many files, this is because most +of the OS files are shared with NZCOM. See here for a list NZ-COM +Z3PLUS OS Files

+

The following file are in User Area 15, and where noted 10 for help +files.

+ + + + + + + + + + + + + + + + + + + + + + + + + +
FileDescription
ALIAS.CMDSample alias definitions for use with ARUNZ
PATCHSK.SUBPatch smartkey II v. 1.0A (U10)
PATCH4SK.HEXPatch smartkey II v. 1.0A - Hex File (U10)
RELEASE.NOTUpdate information on Z3PLUS (U10)
+

Additional Files

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DocumentationUser Area
Testing Applications2
Sample Audio Files3
CP/NET 1.24
SIMH Simulator13
CP/M 3 Files15
NZ-COM Z3PLUS OS Files15, 14, 10
OS General Files15, 14, 10
General Purpose Applications15, 10
+

ZPM3

+

This is a generic ZPM3 adaptation for RomWBW.

+

Floppy Disk Image: fd_zpm3.img
+Hard Disk Image: hd_zpm3.img
+Combo Disk Image: Slice 4

+

Per ZPM3 standard, files are distributed across different user areas +depending on their usage. Normal applications are in user area 15. Help +files in user area 10. Configuration files in user area 14.

+

ZPM3 OS Files

+

The following files appear in User Area 0

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileSourceDescription
BNKBIOS3.SPRRomWBWBanked BIOS
BNKBDOS3.SPRZPM3Banked BDOS
CPM3.SYSRomWBWZPM3 system file (See Note)
GENCPM.DATRomWBWDRI CPM+ System generation tool data file
HELP.HLPZPM3System Help File
MAKEDOS.COMZPM3Utility to overlay your system file with ZPM3
STARTZPM.COMRomWBWCommands to execute after ZPM is launched
RESBDOS3.SPRZPM3Resident BDOS
ZCCP.COMZPM3ZCCP replacement for CCP.COM
ZINSTAL.ZPMZPM3Segment containing environment information
ZPMLDR.COMRomWBWZPM3 Boot Loader Application
ZPMLDR.SYSRomWBWZPM3 Boot Loader for SYSCOPY
+

NOTE: Currently GENCPM.COM is located in User Area 15

+

NOTE: The ZPM3 system file is called CPM3.SYS. This is the ZPM3 +default configuration. It is done to maximize compatibility with CP/M 3.

+

Either ZPMLDR or CPMLDR can be used to launch ZPM3. CPMLDR is equivalent +to ZPMLDR.

+

The following files appear in User Area 15

+ + + + + + + + + + + + + + + + + + + + + + + + + +
FileSourceDescription
AUTOTOG.COMZPM3
CLRHIST.COMZPM3
SETZ3.COMZPM3
+

ZPM3 Files

+

This is a generic ZPM3 adaptation for RomWBW.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileUser AreaDescription
ARUNZ.COM15Alias-RUN-forZ-System command alias exec (v1.1 Type3)
DEV.COM15
DISKINFO.COM15ZCPR utility which gives information about your disks.
DU.COM15
ERASE.CFG14
GENCPM.COM15DRI CPM3 Utility to Create a memory image of CPM3.SYS
GOTO.COM15
HELPC15.CFG14
IF.COM15Extended flow control tester for FCP (v1.6 Type 3)
IF.HLP10
LOADSEG.COM15ZCCP Utility to Load RSXes, TCAPs and Named Directory files.
MENU.HLP10
NAMES.NDR15Default Directory Names loaded at boot
REMOVE.COM15
RSXDIR.COM15ZCPR Utility which displays RSXes in memory
SETPATH.COM15used to set the command search path.
VERROR.COM15Installs a resident error handler
VLU.COM15Video Library Utility views or extracts files from libraries
VLU.HLP10
XREF.COM15
ZERASE.COM15
ZFHIST.HLP10
ZFILER.COM15File management shell, with GUI.
ZFILER.HLP10Help file for ZFILER.COM
ZF11.CFG14
ZFMACRO.HLP10
ZHELP.COM15
ZSHOW.COM15displays amount of information about your Z-System
+

Additional Files

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DocumentationUser Area
Testing Applications2
Sample Audio Files3
SIMH Simulator13
CP/M 3 Files15
OS General Files15, 14, 10
General Purpose Applications15, 10
+

QPM 2.7

+

The following files came from from Microcode Consulting. The official +distribution files can be found on the Microcode Consulting website at +[https://www.microcodeconsulting.com/z80/qpm.htm]. Also included in +this image are debugz, and linkz frm the same company.

+

This disk includes the standard DRI CP/M 2.2 files in addition to the +QP/M files. QP/M generally assumes you already had DRI CP/M 2.2 prior to +adding QP/M features.

+

QPM 2.7 OS Files

+

These are built and provide the OS. QPM Typically has no boot files +stored on the disk. It entirely boots from the system track

+

The following files appear in User Area 0

+ + + + + + + + + + + + + +
FileDescription
QPM.SYSRomWBW configured QP/M system image (for use with SYSCOPY)
+

The qpm.sys file and the QP/M image on the system tracks was created +using QINSTALL with default settings EXCEPT for the two settings +described under Notes (current drive/user storage address and TIMDAT +vector).

+

QPM 2.7 Files

+

The following files appear in User Area 0

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileDescription
D.COMDirectory lister
DBGINST.COMConfigures DEBUGZ debugger
DEBUGZ.COMSymbolic debugger for Z80
DEBUGZ.HLPSymbolic debugger help file
DHORIZ.COMVersion of directory lister for horizontal file sorting
HELLO.QPMText file with QP/M version information
LZ.COMZ80 Linking Loader
QBACKUP.COMData backup application
QINSTALL.COMQP/M installer / configurator
QPATCH.COMPatches (customizes) a few QP/M applications
QPIP.COMQP/M enhanced version of CP/M 2.2 PIP application
QPMCLK.MACExample of QP/M clock assembler routine
QPMCMDS.TXTBrief summary of QP/M commands
QPMUTILS.TXTBrief summary of QP/M utilities
QSTAMP.COMInitializes disk for date/time stamping
QSTAMPV.COMInitializes disk for date/time stamping (vertical sort)
QSTAMPX.COMInitializes disk for date/time stamping (horizontal sort)
QSTAT.COMQP/M enhanced version of CP/M 2.2 STAT application
QSUB.COMQP/M batch file submission program - Like SUBMIT
QSWEEP.COMQP/M directory sweep utility
QTERM.DATTerminal control codes used by DEBUGZ
QTERMS.LIBLibrary of available terminal definitions
SETQTERM.COMConfigures QTERM.DAT
TDCNFG.COMConfigures date/time directory display preferences
+

There are two text files (QPMCMDS.TXT and QPMUTILS.TXT) included.
+These files have escape sequences imbedded in them which makes them look +a little strange depending on the terminal emulation you are using.

+

Additional Files

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DocumentationUser Area
CP/M 2.2 Files0
OS General Files0
General Purpose Applications0
Testing Applications2
Sample Audio Files3
SIMH Simulator13
+

Common Disk Contents

+

CP/NET 1.2

+

User area 4 contains a full implementation of the CP/NET 1.2 client +provided by Doug Miller. Please refer to +[https://github.com/durgadas311/cpnet-z80] for more information, +complete documentation and the latest source code.

+

Please refer to the RomWBW User Guide for instructions on installing and +using these these packages. Either the MT011 RCBus module or the Duodyne +Disk I/O board is required. In general, to use CP/NET on RomWBW, it is +intended that you will extract the appropriate set of files into your +default directory in user area 0.

+

The following are found in

+
    +
  • /Binary/CPNET
  • +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileCP/NET VersionOSHardware
CPN12MT.LBRCP/NET 1.2CP/M 2.2RCBus w/ MT011
CPN3MT.LBRCP/NET 3CP/M 3RCBus w/ MT011
CPN12DUO.LBRCP/NET 1.2CP/M 2.2Duodyne w/ Disk I/O
CPN3DUO.LBRCP/NET 3CP/M 3Duodyne w/ Disk I/O
CPN12SER.LBRCP/NET 1.2CP/M 2.2RomWBW Serial Port
CPN3SER.LBRCP/NET 3CP/M 3RomWBW Serial Port
+

General Purpose Applications

+

The following files are general purpose an provided in (mostly) all OS +images

+

The following files are found in

+
    +
  • /Source/Apps/*
  • +
  • /Source/Images/Common/All
  • +
  • /Source/TastyBasic
  • +
+

The following files provide specific functionality enabled by RomWBW +enhancements. These applications are typically documented in the “RomWBW +Applications.pdf” document in the Doc directory of the RomWBW +Distribution.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileSourceDescription
ASSIGN.COMRomWBWAssign,remove,swap drive letters of RomWBW disk slices
CLRDIR.COMMax ScaneInitializes the directory area of a disk
COPYSL.COMM.PrudenCopy CPM Hard Disk Slices
COPYSL.DOCM.PrudenDocumentation for COPYSL.COM
CPUSPD.COMRomWBWCPU Speed
FAT.COMRomWBWMS-DOS FAT filesystem tool (list, copy, delete, format, etc.)
FDISK80.COMJohn CoffmanHard disk partitioning tool
FDU.COMRomWBWFloppy Disk Utility, Test and format floppy disks
FDU.DOCRomWBWDocumentation for FDU
FLASH.COMWill SowerbuttsProgram FLASH chips in-situ
FLASH.DOCWill SowerbuttsDocumentation for FLASH
FORMAT.COMRomWBWPlaceholder application with formatting instructions
HTALK.COMTom PlanoTerminal utility talking directly to HBIOS Character Units
MODE.COMRomWBWChange serial line characteristics (baud rate, etc.)
REBOOT.COMMartinRCold or Warm Boot the RomWBW System
RTC.COMAndrew LynchTest real time clock hardware on your system
SURVEY.COMRomWBWDisplay system resources summary
SYSCOPY.COMRomWBWCopy system tracks to disks (make bootable)
TALK.COMRomWBWRoute console I/O to & from specified serial port
TIMER.COMRomWBWTest and display system timer ticks
TUNE.COMRomWBWPlay .PT2, .PT3, and .MYM audio files on supported hardware
VGMPLAY.COMSimple player for VGM (Video Game Music) files.
WDATE.COMKevin BooneUtility to configure RTC Date.
XM.COMRomWBWXModem file transfer application
+

Then we have some more general purpose applications. In general, there +is no documentation for these applications included with the RomWBW +distribution. Some provide command line help themselves. Some are fairly +obvious.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileSourceDescription
BBCBASIC.COMR.T.RussellBBC BASIC CP/M Version
BBCBASIC.TXTR.T.RussellHelp file for BBC BASIC
COMPARE.COMCompare content of two files (binary)
CRUNCH.COMCompress file(s) using Crunch algorithmn
CRUNCH28.CFGZCNFG configuration file for CRUNCH & UNCR
DDTZ.COMZ80 debug tool (modified to use RST 6)
DDTZ.DOCDocumentation for DDTZ
EX.COMBatch file processor (alternative to DRI SUBMIT)
FIND.COMJay CottonSearch all drives for a file ()
GENHEX.COMGenerates an Intel Hex file from the input file
LS.COMAn alternative file listing to DIR
LSWEEP.COMExtract and view member files of an .LBR archive
MBASIC.COMMicrosoftMicrosoft BASIC language interpreter
NULU.COMNZCOM new library utility (.LBR) management tool
PMARC.COMCreate or add file(s) to LHA .PMA archive
PMEXT.COMExtract file(s) from .PMA/.LZH/.LHA archive
RMXSUB1.COMLars NelsonRemove XSUB1 RSX from memory
SUPERSUB.COMEnhanced replacement for DRI SUBMIT
SUPERSUB.DOCDocumentation for SUPERSUB
SYSGEN.COMDRICopy system tracks to disks
TBASIC.COMDimitri TheulingsTasty Basic. This also exists as a Rom appication
TDLBASIC.COMTDL Zapple 12K BASIC language interpreter
TE.COMLadislau SzilagyiRomWBW enhanced version of TE editor
TE.DOCLadislau SzilagyiTE Editor Documentation
UNARC.COMExtract file(s) from .ARC or .ARK archive
UNARC.DOCDocumentation for UNARC
UNCR.COMDecompress Crunched file(s). See CRUNCH.COM
UNZIP.COMLars NelsonUNZIP extracts from MS-DOS ZIP files
UNZIP.DOCDocumentation for UNZIP
XSUB1.COMLars NelsonReplacement for DRI XSUB
ZAP.COMInteractive disk & file utility
ZDE.COMCompact WordStar-like editor
ZDE.DOCZDE Documentation
ZDENST.COMInstallation/configuration tool for ZDE
ZMRX.COM
ZMTX.COM
ZMD.COMR.W.KZ80 RCP/M File Transfer Program (Robert W. Kramer III)
ZMP.COMZModem communications program (dedicated port)
ZMP.DOCDocumentation for ZMP
ZMP.HLPHelp file for ZMP
ZMXFER.OVROverlay file for ZMP
ZMTERM.OVROverlay file for ZMP
ZMINIT.OVROverlay file for ZMP
ZMCONFIG.OVROverlay file for ZMP
+

OS General Files

+

The following files are spcific files share across several OS’s.
+In general, there is no documentation for these applications included +with the RomWBW distribution. Some provide command line help +themselves.
+Some are fairly obvious.

+

The following files are found in

+
    +
  • /Source/Images/Common/CPM22
  • +
  • /Source/Images/Common/CPM3
  • +
  • /Source/Images/Common/Z
  • +
  • /Source/Images/Common/Z3
  • +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileApplicabilityDescription
ALIAS.COMZ3Create an Alias (v1.1)
ALIAS.HLPZ3Help File for ALIAS.COM
COPY.COMZFile copier with ZSDOS date stamping awareness
COPY.CFGZZCNFG configuration file for COPY application
EDITNDR.COMZ3Edit named directory register in memory.
HP-RPN.HLPZ3Help File for ZP.COM - HP RPN Calculators
HP-ZP.HLPZ3Help File for ZP.COM - HP ZP Calculators
KERCPM22.COMCPM22Kermit communication application
KERCPM3.COMCPM3Kermit communication application
LBREXT.COMZExtract file from .LBR libraries
LBREX36.CFGZZCNFG configuration file for LBREXT
RZ.COMCPM3Receive files with X/Y/ZModem (experimental)
RZSC.FORCPM3Description of RZ/SZ programs
SAINST.COMZ3Install/configure SALIAS.
SALIAS.COMZ3Screen oriented alias editor. (v1.6)
SAVENDR.COMZ3Writes the named directory to disk.
SDZ.COMZ3Enhanced directory lister.
SCOPY.COMZ3Screen-oriented file copy for ZCPR3
SCOPY10.CFGZ3ZCNFG configuration file for SCOPY
SCOPY.HLPZ3Primary help file for SCOPY
SCOPY10F.HLPZ3Secondary help file for SCOPY
SZ.COMCPM3Send files with X/Y/ZModem (experimental)
TCAP.Z3TZ3Terminal capabilities for ZCPR3 (VT100)
TCSELECT.COMZ3NZCOM Create terminal capability file (newer version)
TCVIEW.COMZ3View zcpr3 terminal capabilities
UMAP.COMZ3Shows directory usage
UMAP18.CFGZ3ZCNFG configuration file for UMAP program
UNARCU1.CFGZZCNFG configuration file for UNARC program
ZCNFG.COMZConfiguration tool for programs with .CFG files
ZCNFG24.CFGZConfiguration file for ZCNFG.COM
ZEX.COMZ3A memory-based command file processor, like SUBMIT
ZEX.CFGZ3ZCNFG configuration file for ZEX program
ZP.COMZ3Screen-oriented file/disk/memory record patcher (ZAP)
ZP.HLPZ3Help File for ZP.COM
ZP17.CFGZ3Configuration file for ZP.COM
ZXD.CFGZConfiguration file for ZXD.COM
ZXD.COMZExtended directory utility w/ date/time stamp support
Z3LOC.COMZ3Display info of the ZCPR3 CCP, BDOS, and BIOS
Z3TCAP.LBRZ3Database of terminal descriptions
+

Applicability:

+
    +
  • CPM22 - Included in all CP/M 2.2 OS’s (CPM2.2, ZSDOS, NZ-COM, QPM)
  • +
  • CPM3 - Included in all CP/M 3 OS’s (CPM3, Z3PLUS, ZPM3)
  • +
  • Z - Included in All Z OS’s (ZSDOS, NZ-COM, Z3PLUS, ZPM3)
  • +
  • Z3 - Included in ZCPR3 OS’s (NZ-COM, Z3PLUS, ZPM3)
  • +
+

NZ-COM Z3PLUS OS Files

+

The following files are specific files share across two operating +systems.

+
    +
  • NZ-COM - The Automatic Z-System - Alpha Systems
  • +
  • Z3PLUS - The Z-System for CP/M-Plus - Plu*Perfect Systems
  • +
+

These 2 operating systems are identical in all respects, except for the +underlying operating system that they run on.

+

The following files are found in

+
    +
  • /Source/Images/Common/NZ3PLUS
  • +
+

The following file are in User Area 15, and where noted 14 for config +files.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileDescription
ARUNZ.COMAlias-RUN-forZ-System command alias exec (v0.9u Type4)
CLEDINST.COMCommand line editing and history shell installer
CLEDSAVE.COMSave RCP-resident command line editor history
CONFIG.LBRVarious configuration files for use with ZCNFG. (U14)
CPSET.COMDisplays/defines CRT/PRT characteristics
FCP.LBRLibrary of alternative FCP modules
FF.COMFile finder utility
IF.COMExtended flow control tester for FCP (v1.5 Type4)
JETLDR.COMZ-System General-purpose module loader
LBRHELP.COMHelp file viewer for use with help file libraries (.LBR)
LDIR.COMDirectory lister for libraries (.LBR)
LPUT.COMPuts file(s) into a library (.LBR)
LSH.COMCommand history shell and command line editor
LSH-HELP.COMDisplay LSH help when LSH is running
LSHINST.COMLSH configuration editor
LX.COMExecute programs directly from a library (.LBR)
NAME.COMQuickly add or remove a name for a single directory
PATH.COMSet/display command search path
PWD.COMDisplays DU and Directory Names with paging
TY3ERA.COMType-3 program to erase a file
TY3REN.COMType-3 program to rename a file
TY4ERA.COMType-4 program to erase a file
TY4REN.COMType-4 program to rename a file
TY4SAVE.COMType-4 program to save memory to a file
TY4SP.COMType-4 program to display disk space
VIEW.COMQuad directional file viewer
XTCAP.COMInteractive Extended TCAP Installer
ZERR.COMZ34 Error Handler
ZF-DIM.COMZFILER shell for dim-video terminals
ZF-REV.COMZFILER shell for reverse-video terminals
ZFILER.CMDMacro script file for ZFILER
ZHELP.COM(HELPC14) is an improved version of the help utility
ZLT.COMFile lister with support for compressed files
ZSHOW.COMDisplay Z-System configuration information
+

The following documentation files are in User Area 10

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileDescription
DOCFILES.LBRDocumentation and help files collected into an LBR file
HLPFILES.LBRVarious app help files for use with LBRHELP
LSH.WZUser manual for LSH
TCJ.INFSubscription information for The Computer Journal
TCJ*.WZSelected articles from The Computer Journal
ZFILEB38.LZTBrief listing of Z-System support programs
ZHELPERS.LZTList of volunteers who will help installing Z-System
ZNODES66.LZTList of Z-Node remote access systems
ZSYSTEM.IZFInformation on Z-System and related products
+

Sample Audio Files

+

User area 3 contains sample audio files that can be played using the +TUNE or VGMPLAY applications.

+

NOTE These files are NOT present on floppy disk images

+

The following files are found in

+
    +
  • /Binary/Apps/Tunes
  • +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileFileFileFile
ATTACK.PT3DEMO4.MYMNAMIDA.PT3VICTORY.PT3
BACKUP.PT3ENDING.VGMRECOLL.PT3WICKED.PT3
BADMICE.PT3HOWRU.PT3SANXION.PT3WONDER01.VGM
DEMO.MYMINCHINA.VGMSHIRAKAW.VGMYEOLDE.PT3
DEMO1.MYMITERATN.PT3STARTDEM.VGMYEOVIL.PT3
DEMO3.MYMLOOKBACK.PT3SYNCH.PT3
DEMO3MIX.MYMLOUBOUTN.PT3TOSTAR.PT3
+

SIMH Simulator

+

Files for use with the SIMH Simulator

+

The following files are found in

+
    +
  • /Source/Images/Common/SIMH
  • +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileDescription
HDIR.COM
R.COMtransfer files between the simulator and host file system
RSETSIMH.COM
TIMER.COM
URL.COM
W.COMtransfer files between the simulator and host file system
+

Testing Applications

+

User area 2 contains a variety of hardware testing applications. These +are generally user contributed and have no documentation.

+

These applications are frequently not compatible with all RomWBW +hardware. They are included here as a convenience. If applicable, your +hardware documentation should refer to them and provide usage +instructions.

+

NOTE These files are NOT present on floppy disk images

+

The following files are found in

+
    +
  • /Binary/Apps/Test
  • +
  • /Source/Images/Common/Test
  • +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileDescription
2PIOTST.COMECB-ZILOG PERIPHERALS BOARD TEST 2 PIO’s
AY-TEST.COMAY-3-8910 Sound Test Program (SOUND)
BANKTEST.COMTest RomWBW bank management API
DMAMON.COMVerify operation of the Z80 MBC DMA board
I2CLCD.COMPCF8584 HD44780 I2C LCD UTILITY
I2CSCAN.COMI2C BUS SCANNER
INTTEST.COMTest HBIOS interrupt API functions
KBDTEST.COMtest program to work with the Z80 KBDMSE board
PIOMON.COMZilog PIO Monitor & Hardware Testing Application
PORTSCAN.COMReads all ports and displays values read
PPIDETST.COMPPI IDE test for checkout of all 8255 IDE drives
PS2INFO.COMPS/2 Keyboard/Mouse Information Utility
RAMTEST.COMRAM_TEST_PROGRAM
RTCDS7.COMPCF8584/DS1307 I2C DATE AND TIME UTILITY (I2C)
RZ.COMReceive Zmodem disassembly of CP/M 3 binaries
SOUND.COMRomWBW HBIOS Sound Device Test Tool (SOUND)
SROM.COMI2C Serial ROM Read/Write Utility (I2C)
SZ.COMSend Zmodem is a disassembly of CP/M 3 binaries
TESTH8P.COMH8 Panel Test
TSTDSKNG.COMDSKY NEXT GENERATION TEST APPLICATION
VDCONLY.COMCOLOR VDU TEST
VDCTEST.COMCOLOR VDU TEST
ZEXALL.COMZ80 Instruction Set Exerciser
ZEXDOC.COMZ80 Instruction Set Exerciser
+

And The following CPU Tests - Which are probably originally from this +source. [https://github.com/raxoft/z80test]

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileDescription
Z80CCF.COMtests flags after executing CCF after each instruction.
Z80DOC.COMtests registers, but only officially documented flags
Z80DOCF.COM
Z80FLAGS.COMtests flags, ignores registers.
Z80FULL.COMtests flags and registers
Z80MPTR.COMtests flags after executing BIT N,(HL) after each instruction
+

Application Standalone Disks

+

Aztec C Compiler

+

Floppy Disk Image: fd_aztecc.img
+Hard Disk Image: hd_aztecc.img

+

Aztec C is a discontinued programming language for a variety of +platforms including MS-DOS, Apple II DOS 3.3 and PRoDOS, Commodore 64, +Macintosh and Amiga. This disk contains the CP/M version of that +compiler. A cross-compiler for MS-DOS or Windows XP is also available.

+

For full documentation, see [https://www.aztecmuseum.ca] The user +manual is available in the Doc/Language directory +Aztec_C_1.06_User_Manual_Mar84.pdf

+

The following files are found in

+
    +
  • /Source/Images/d_aztec
  • +
+ + + + + + + + + + + + + +
FileDescription
+

NOTE : The above is incomplete

+

Microsoft Basic Compiler

+

Floppy Disk Image: fd_bascomp.img
+Hard Disk Image: hd_bascomp.img

+

The Microsoft BASIC Compiler is a highly efficient programming tool that +converts BASIC programs from BASIC source code into machine code. This +provides much faster BASIC program execution than has previously been +possible. It can make programs run an average of 3 to 10 times faster +than programs run under BASIC-80. Compiled programs can be up to 30 +times faster than interpreted programs if maximum use of integer +variables is made.

+

View BASCOM.HLP included in the disk image using HELP.COM for +documentation.

+

The following files are found in

+
    +
  • /Source/Images/d_bascomp
  • +
+ + + + + + + + + + + + + +
FileDescription
+

NOTE : The above is incomplete

+

Cowgol Compiler

+

Floppy Disk Image: fd_cowgol.img
+Hard Disk Image: hd_cowgol.img

+

The Cowgol 2.0 compiler and related tools. These files were provided by +Ladislau Szilagyi and were sourced from his GitHub repository at +[https://github.com/Laci1953/Cowgol_on_CP_M].

+

The primary distribution site for Cowgol 2.0 is at +[https://github.com/davidgiven/cowgol]. The user manual is available +in the Doc/Language directory Cowgol Language.pdf

+

The following files are found in

+
    +
  • /Source/Images/d_cowgol
  • +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileDescription
ADVENT.COWAdventure game program source
ADVENT.SUBSubmit file to build ADVENT
ADVENT?.TXTAdventure game program resource
ADVMAIN.COWAdventure game program source
RAND.ASAssembler Library File
COWBE.COM
COWFE.COMRomWBW specific (Memory Manage) version
COWLINK.COM
DYNMSORT.COWdemonstrates a sort algorithm
DYNMSORT.SUBSubmit file to build DYNMSORT
HEXDUMP.COWa simple hex dump utility, purely a Cowgol
HEXDUMP.SUBSubmit file to build HEXDUMP
HMERGES.CC Library File
XRND.ASAssembler Library File
--
+

NOTE : The above is incomplete

+

Microsoft Fortran 80 (Fortran)

+

Floppy Disk Image: fd_fortran.img
+Hard Disk Image: hd_fortran.img

+

This is Microsoft’s implementation of the FORTRAN scientific-oriented +high level programming language. It was one of their early core +languages developed for the 8-bit computers and later brought to the +8086 and IBM PC. In 1993 Microsoft rebranded the product as Microsoft +Fortran Powerstation. (Note: -80 refers to the 8080/Z80 platform, not +the language specification version)

+

The user manual is available in the Doc/Language directory, +Microsoft_FORTRAN-80_Users_Manual_1977.pdf

+

The following files are found in

+
    +
  • /Source/Images/d_fortram
  • +
+ + + + + + + + + + + + + +
FileDescription
+

NOTE : The above is incomplete

+

Games

+

Floppy Disk Image: fd_games.img
+Hard Disk Image: hd_games.img

+

This disk contains several games for CP/M including the Infocom games +Zork 1 through 3, Planetfall and Hitchhiker’s Guide to the Galaxy.

+

Nemesis and Dungeon Master is a Rogue-like game released in 1981. It is +playable on a text terminal using ASCII graphics to represent the +dungeon. Only a few thousand copies of the game were ever made, making +it very rare. See +[http://crpgaddict.blogspot.com/2019/03/game-322-nemesis-1981.html]

+

Colossal Cave Adventure is a CP/M port of the 1976 classic game +originally written by Will Crowther for the PDP-10 mainframe. See +[https://en.wikipedia.org/wiki/Colossal_Cave_Adventure] and +[https://if50.substack.com/p/1976-adventure]

+

The following files are found in

+
    +
  • /Source/Images/d_games
  • +
+ + + + + + + + + + + + + +
FileDescription
+

NOTE : The above is incomplete

+

HI-TECH C Compiler

+

Floppy Disk Image: fd_hitechc.img
+Hard Disk Image: hd_hitechc.img

+

The HI-TECH C Compiler is a set of software which translates programs +written in the C language to executable machine code programs. Versions +are available which compile programs for operation under the host +operating system, or which produce programs for execution in embedded +systems without an operating system.

+

This is the Mar 21, 2023 update 17 released by Tony Nicholson who +currently maintains HI-TECH C at +[https://github.com/agn453/HI-TECH-Z80-C]

+

The manual is available in the Doc/Language directory, HI-TECH Z80 C +Compiler Manual.txt

+

A good blog post about the HI-TECH C Compiler is available at +[https://techtinkering.com/2008/10/22/installing-the-hi-tech-z80-c-compiler-for-cpm]

+

The following files are found in

+
    +
  • /Source/Images/d_hitechc
  • +
+ + + + + + + + + + + + + +
FileDescription
+

NOTE : The above is incomplete

+

MSX ROMS

+

Hard Disk Image: hd_msxroms1.img
+Hard Disk Image: hd_msxroms2.img

+

The collection of MSX ROMs (2 disks) as provided by Les Bird.
+These ROMs are “run” by using the appropriate variant of Les’ MSX8 ROM +loader. You can download the loader binaries from +[https://github.com/lesbird/MSX8]. You will need appropriate hardware +to run the loader.

+

Please review the file ROMLIST.TXT for information on the current +operational status of the ROM and it’s long file name/description.

+

This disk (RomWBW slice) is not automatically included with the RomWBW +“combo” disk images. You can simply add it to a combo image by appending +it to the end. After booting your system, you can use the ASSIGN command +to map the slice to a drive letter. Refer to the RomWBW User Guide for +more information on this process.

+

The ROM files are found in

+
    +
  • /Source/Images/d_msxroms1
  • +
  • /Source/Images/d_msxroms2
  • +
+

Turbo Pascal Compiler

+

Floppy Disk Image: fd_tpascal.img
+Hard Disk Image: hd_tpascal.img

+

The Borland Turbo Pascal Compiler. Pascal is a general-purpose, high +level programming language originally designed by Professor Niklaus +Wirth of the Technical University of Zurich, Switzerland and named in +honor of Blise Pascal, the famous French philosopher and mathematician.

+

Turbo Pascal closely follows the definition of Standard Pascal as +defined in the Pascal User Manual and Report with a few minor +differences.

+

The manual can be found in the Docs/Language directory, +Turbo_Pascal_Version_3.0_Reference_Manual_1986.pdf

+

A good overview of using Turbo Pascal in CP/M is available at +[https://techtinkering.com/2013/03/05/turbo-pascal-a-great-choice-for-programming-under-cpm]

+

The following files are found in

+
    +
  • /Source/Images/d_tpascal
  • +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileDescription
ART.TXTPart of the Example program
SA.PASExample Program
TINST.COMInstallation and Configuration
TINST.DTAPart of TINST
TINST.MSGPart of TINST
TURBO.COMThe main Turbo Pascal program
TURBO.MSGPart of TURBO tascal
TURBO.OVRPart of TURBO tascal
TURBOMSG.OVRPart of TURBO tascal
+

WordStar 4

+

Floppy Disk Image: fd_ws4.img
+Hard Disk Image: hd_ws4.img
+Combo Disk Image: Slice 5

+

The following files are found in

+
    +
  • /Source/Images/d_ws4
  • +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileDescription
ANAGRAM.COM
CHAPTER1.DOC
CHAPTER2.DOC
CHAPTER3.DOC
DIARY.DOC
DICTSORT.COM
FIND.COM
HOMONYMS.TXT
HYEXCEPT.TXT
HYPHEN.COM
LOOKUP.COM
MAINDICT.CMP
MARKFIX.COM
MOVEPRN.COM
PATCH.LST
PRINT.TST
READ.ME
README.
REVIEW.COM
RULER.DOC
SAMPLE1.DOC
SAMPLE2.DOC
SAMPLE3.DOC
SPELL.COM
TABLE.DOC
TEXT.DOC
TW.COM
WC.COM
WINSTALL.COM
WORDFREQ.COM
WS.COM
WS.OVR
WSCHANGE.COM
WSCHANGE.OVR
WSCHHELP.OVR
WSHELP.OVR
WSINDEX.XCL
WSMSGS.OVR
WSPRINT.OVR
WSSHORT.OVR
+

Also contained on this image in User Area 1 are.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileDescription
SAMPKEY.DOCZDE Distribution File
SAMPKEY.ZDKZDE Distribution File
SAMPKEY.ZDTZDE Distribution File
ZDE10.DOCZDE Distribution File
ZDE10.FORZDE Distribution File
ZDE10.NEWZDE Distribution File
ZDE10.QRFZDE Distribution File
ZDE10.TOCZDE Distribution File
ZDE13.FORZDE Distribution File
ZDE13.NEWZDE Distribution File
ZDE16.COMZDE Distribution File
ZDE16.DIRZDE Distribution File
ZDE16.FIXZDE Distribution File
ZDE16.FORZDE Distribution File
ZDE16.NEWZDE Distribution File
ZDE16A.COMZDE Distribution File
ZDE16A.PATZDE Distribution File
ZDENST16.COMZDE Distribution File
ZDEPROP.DOCZDE Distribution File
ZDEPROP.Z80ZDE Distribution File
ZDKCOM13.COMZDE Distribution File
ZDKCOM13.DOCZDE Distribution File
+

Z80ASM Macro Assembler

+

Floppy Disk Image: fd_z80asm.img
+Hard Disk Image: hd_z80asm.img

+

This disk contains 6 major components

+
    +
  • +

    Z80ASM is a relocating macro assembler for CP/M. It takes assembly + language source statements from a disk file, converts them into their + binary equivalent, and stores the output in either a core-image, Intel + hex format, or relocatable object file. The mnemonics recognized are + those of Zilog/Mostek. The optional listing output may be sent to a + disk file, the console and/or the printer, in any combination. Output + files may also be generated containing cross-reference information on + each symbol used.

    +
  • +
  • +

    Z80ASMP (Z80ASM Plus). Referred to as the “Virtual Memory” version + which uses disk for working storage, thus not constrained by RAM.

    +
  • +
  • +

    SLR180 is a powerful relocating macro assembler for Z80 compatible + CP/M systems. It takes assembly language source statements from a disk + file, converts them into their binary equivalent, and stores the + output in either a core-image, Intel hex format, or relocatable object + file. The mnemonics recognized are those of Zilog (Z180)/Hitachi. The + optional listing output may be sent to a disk file, the console and/or + the printer, in any combination. Output files may also be generated + containing cross-reference information on each symbol used.

    +
  • +
  • +

    SLRMAC relocating macro assembler for Intel 8080 mnemonics

    +
  • +
  • +

    SLRNK is a powerful linking loader for Z80-based CP/M systems. It + takes relocatable binary information in either Microsoft or SLR + Systems format from a disk file, resolves external and entry point + references, and stores the output in memory for execution or outputs + it to a disk file.

    +
  • +
  • +

    SLRNKP (SLRNK Plus). Referred to as the “Virtual Memory” version which + uses disk for working storage, thus not constrained by RAM.

    +
  • +
  • +

    Z80DIS is an entirely new disassembler for Z80 based CP/M sys- tems. + Z80DIS is written in TURBO PASCAL. Z80DIS generates Z80 mnemonics and + prepares an assembly language file with many special features for ease + of understanding the intent of the code. The program and documantation + are Copyright 1985, by Kenneth Gielow, Palo Alto, CA. All rights are + reserved.

    +
  • +
+

The manual(s) are available in the Doc/Language directory,

+
    +
  • z80asm (SLR Systems).pdf
  • +
  • SL180 (SLR Systems 1985).pdf
  • +
  • SLRNK (SLR Systems 1984).pdf
  • +
  • Z80DIS User Manual (1985).pdf
  • +
+

A run through of using the assembler is available at +[https://8bitlabs.ca/Posts/2023/05/20/learning-z80-asm]

+

And another shorter, but shows linker usage guide +[https://pollmyfinger.wordpress.com/2022/01/10/modular-retro-z80-assembly-language-programming-using-slr-systems-z80asm-and-srlnk/]

+

The following files are found in

+
    +
  • /Source/Images/d_z80asm
  • +
+

User Area 0 - Assembler

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileDescription
180FIG.COMConfiguration utility for SLR180.COM
8080.MAC?
CONFIG.COMConfiguration utility for Z80ASM.COM
CONFIGP.COMConfiguration utility for Z80ASMP.COM
DUMP.*Sample Program
MAKESYM.COMSymbol File .SYM file generation
MAKESYM.DOCDocumentation for MAKESYM.COM
SLR180.COMHD64180 (Z180) Relocating Macro Assembler
SLR180.DOCRelease Notes for SLR180.COM
SLRMAC.COM8080 Relocating Macro Assembler
SYNTAX.HLPDocumentation basic usage for all SLR Tools
SYNTAX.TXTDocumentation basic usage for all SLR Tools
TEST.*Sample Program
Z80ASM.COMZ80 Relocating Macro Assembler
Z80ASMP.COMZ80 Relocating Macro Assembler (PLUS)
Z80ASM.DOCRelease Notes for Z80ASM.COM
+

User Area 1 - Linker and Library Management

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileDescription
LNKFIG.COMConfiguration utility for SLRNK.COM
NZLNKFIX.ZEX?
SLRIB.COMSuperLibrarian, library manager
SLRNK.COMSuperLinker, the main linker tool
SLRNKP.COMSuperLinker (PLUS)
SLRNK.DOCRelease Notes for SLRNK.COM
SLRNKFIX.ZEX?
SYNTAX.HLPDocumentation basic usage for all SLR Tools
SYNTAX.TXTDocumentation basic usage for all SLR Tools
SYSSLR.RELSYSLIB (older) Library compatible with SLR
VSLR.RELVLIB (older) Library compatible with SLR
Z3SLR.RELZ3LIB (older) Library compatible with SLR
+

User Area 2 - Disassembler

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileDescription
README.22Documentation for Z80DIS
Z80DIS.000Overlay File for Z80DIS.COM
Z80DIS.001Overlay File for Z80DIS.COM
Z80DIS.002Overlay File for Z80DIS.COM
Z80DIS.COMZ80DIS Disassembler main program
Z80DIS22.DOCMain Documentation for Z80DIS
ZDINSTAL.COMInstal and Config for Z80DIS.COM
ZDINSTAL.DTAOverlay file for ZDINSTAL.COM
ZDINSTAL.MSGOverlay file for ZDINSTAL.COM
+
+
+ + + + + + + + + + + diff --git a/Hardware/index.html b/Hardware/index.html new file mode 100644 index 00000000..6e27b0e6 --- /dev/null +++ b/Hardware/index.html @@ -0,0 +1,4575 @@ + + + + + + + + + + + Hardware - RomWBW Documentation V3.6 + + + + + + + + + + + + + + + + +
+
+
+
+ +

RomWBW Hardware \ +Version 3.6 \ +Wayne Warthen (wwarthen@gmail.com) \ +30 May 2025

+

Overview

+

Supported Platforms

+

This section contains a summary of the system configuration target for +each of the pre-built ROM images included in the RomWBW distribution.

+

It is intended to help you select the correct ROM image and understand +the basic hardware components supported. Detailed hardware system +configuration information should be obtained from your system +provider/designer.

+

The table below summarizes the hardware platforms currently supported by +RomWBW along with the standard pre-built ROM image(s).

+

RCBUS - General Configurations

+

RCBus refers to Spencer Owen’s RC2014 bus specification and derivatives +including RC26, RC40, RC80, and BP80.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DescriptionBusROM Image FileBaud Rate
RCBus Z80 CPU Module, 512K RAM/ROMRCBusRCZ80_std.rom115200
RCBus Z80 CPU Module (KIO), 512K w/KIORCBusRCZ80_kio_std.rom115200
RCBus Z180 CPU Module (External)RCBusRCZ180_ext_std.rom115200
RCBus Z180 CPU Module (Native)RCBusRCZ180_nat_std.rom115200
RCBus Z280 CPU Module (External)RCBusRCZ280_ext_std.rom115200
RCBus Z280 CPU Module (Native)RCBusRCZ280_nat_std.rom115200
+

KIO refers to a Zilog specific Serial/Parallel Counter/Timer (Z84C90).

+

The RCBus Z180 & Z280 require a separate RAM/ROM memory module. There +are two types of these modules, you must pick the correct ROM for your +type of memory module:

+
    +
  • +

    The first type of RAM/ROM module includes Z2 style memory bank + switching on the memory module itself. This is called “External” (ext) + because the bank switching is external from the CPU itself.

    +
  • +
  • +

    The second type of RAM/ROM module has no bank switching logic on the + memory module. Bank switching is implemented via the Z180 or Z280 MMU + – this is called “Native” (nat) because the CPU itself provides the + bank switching logic.

    +
  • +
+

Only Z180 and Z280 CPUs have the ability to do bank switching in the +CPU, so the ext/nat selection only applies to them. Z80 CPUs have no +built-in bank switching logic, so they always require a RAM/ROM module +with Z2 style bank switching and the ROMs are always configured for +external bank switching.

+

Custom / Specific Configurations

+

Andrew Lynch

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DescriptionBusROM Image FileBaud Rate
RetroBrew Z80 SBC V2ECBSBC_std.rom38400
RetroBrew Z80 SimH-SBC_simh.rom38400
Duodyne Z80 SystemDuoDUO_std.rom38400
Nhyodyne Z80 MBCMBCMBC_std.rom38400
Rhyophyre Z180 SBC-RPH_std.rom38400
N8 Z180 SBC (date >= 2312)ECBN8_std.rom38400
+

Bill Shen

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DescriptionBusROM Image FileBaud Rate
EaZy80-512 Z80 CPU ModuleRCBusRCZ80_ez512_std.rom115200
K80W Z80 CPU ModuleRCBusRCZ80_k80w_std.rom115200
ZRC Z80 CPU ModuleRCBusRCZ80_zrc_std.rom115200
ZRC Z80 CPU Module (RAM)RCBusRCZ80_zrc_ram_std.rom115200
ZRC512 Z80 CPU ModuleRCBusRCZ80_zrc512_std.rom115200
Z1RCC Z180 CPU ModuleRCBusRCZ180_z1rcc_std.rom115200
ZZRCC Z280 CPU ModuleRCBusRCZ280_zzrcc_std.rom115200
ZZRCC Z280 CPU Module (RAM)RCBusRCZ280_zzrcc_ram_std.rom115200
ZZ80MB Z280 SBCRCBusRCZ280_zz80mb_std.rom115200
+

Sergey Kiselev

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DescriptionBusROM Image FileBaud Rate
Easy Z80 SBCRCBusEZZ80_easy_std.rom115200
Tiny Z80 SBCRCBusEZZ80_tiny_std.rom115200
Z80-512K CPU/RAM/ROM ModuleRCBusRCZ80_skz_std.rom115200
Zeta Z80 SBC , ParPortProp-ZETA_std.rom38400
Zeta V2 Z80 SBC , ParPortProp-ZETA2_std.rom38400
+

Stephen Cousins

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DescriptionBusROM Image FileBaud Rate
SC126 Z180 SBCBP80SCZ180_sc126_std.rom115200
SC130 Z180 SBCRCBusSCZ180_sc130_std.rom115200
SC131 Z180 Pocket Comp-SCZ180_sc131_std.rom115200
SC140 Z180 CPU ModuleZ50SCZ180_sc140_std.rom115200
SC503 Z180 CPU ModuleZ50SCZ180_sc503_std.rom115200
SC700 Z180 CPU ModuleRCBusSCZ180_sc700_std.rom115200
+

Others

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DescriptionBusROM Image FileBaud Rate
Dyno Z180 SBC6DynoDYNO_std.rom38400
EP Mini-ITX Z18011UEXTEPITX_std.rom115200
eZ80 for RCBus Module13, 512K RAM/ROMRCBusRCEZ80_std.rom115200
Genesis Z180 System12STDGMZ180_std.rom115200
Heath H8 Z80 System10H8HEATH_std.rom115200
NABU w/ RomWBW Option Board10NABUNABU_std.rom115200
S100 Computers Z180 SBC9S100S100_std.rom57600
S100 Computers FPGA Z80 SBC9S100FZ80_std.rom9600
UNA Hardware BIOS3-UNA_std.rom-
Z80-Retro SBC8-Z80RETRO_std.rom38400
Z180 Mark IV SBC3ECBMK4_std.rom38400
+

3Designed by John Coffman
+6Designed by Steve Garcia
+8Designed by Peter Wilson
+9Designed by John Monahan
+10Designed by Les Bird
+11Designed by Alan Cox
+12Designed by Doug Jackson
+13Designed by Dean Netherton

+

General Guidance

+

The standard ROM images will detect and install support for certain +devices and peripherals that are on-board or frequently used with each +platform. If the device or peripheral is not detected at boot, the ROM +will simply bypass support appropriately.

+

Each ROM will support a single memory manager. This is determined by the +build configuration and is not dynamically selected. The use of the term +Memory Manager is generally synonymous with Memory Management Unit +(MMU).

+

In some cases, support for multiple hardware components with potentially +conflicting resource usage are handled by a single ROM image. It is up +to the user to ensure that no conflicting hardware is in use.

+

CPU speed will be dynamically measured at startup if DSRTC is present

+

All pre-built ROM images are pure binary files (they are not “hex” +files). They are intended to be programmed starting at the very start of +the ROM chip (address 0). Most of the pre-built images are 512KB in +size. If your system utilizes a larger ROM, you can just program the +image into the first 512KB of the ROM for now.

+

For this document port addresses IO=xxx are represented in decimal.

+

The PropIO support is based on RomWBW specific firmware. Be sure to +program/update your PropIO firmware with the corresponding firmware +image provided in the Binary directory of the RomWBW distribution.

+

The use of high density floppy disks requires a CPU speed of 8 MHz or +greater.

+

Platform Configurations

+

Duodyne Z80 System

+

Duodyne is a third generation ROMWBW focused retrocomputer incorporating +lessons learned and improvements from my original ECB Z80 SBC (aka +N8VEM) and the nhyodyne modular computer. It is literally designed +around ROMWBW from the start for a robust OS and software environment.

+

Duodyne is a new design which integrates many functions into larger, +modular boards on a backplane. The intent is to create a powerful and +capable system like an SBC, but with modularity and an expandable +backplane.

+ +

ROM Image File: DUO_std.rom

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BusDuo
Default CPU Speed8.000 MHz
InterruptsMode 2
System TimerCTC
Serial Default38400 Baud
Memory ManagerZ2
ROM Size512 KB
RAM Size512 KB
+

Supported Hardware

+
    +
  • FP: LEDIO=66, SWIO=66
  • +
  • DSRTC: MODE=STD, IO=148
  • +
  • PCF: IO=86
  • +
  • UART: IO=88
  • +
  • UART: IO=168
  • +
  • UART: IO=112
  • +
  • UART: IO=120
  • +
  • SIO MODE=ZP, IO=96, CHANNEL A, INTERRUPTS ENABLED
  • +
  • SIO MODE=ZP, IO=96, CHANNEL B, INTERRUPTS ENABLED
  • +
  • LPT: MODE=SPP, IO=72
  • +
  • DMA: MODE=DUO, IO=64
  • +
  • CH: IO=78
  • +
  • CHUSB: IO=78
  • +
  • CHSD: IO=78
  • +
  • MD: TYPE=RAM
  • +
  • MD: TYPE=ROM
  • +
  • FD: MODE=DUO, IO=128, DRIVE 0, TYPE=3.5” HD
  • +
  • FD: MODE=DUO, IO=128, DRIVE 1, TYPE=3.5” HD
  • +
  • PPIDE: IO=136, MASTER
  • +
  • PPIDE: IO=136, SLAVE
  • +
  • SD: MODE=MT, IO=140, UNITS=1
  • +
  • SPK: IO=148
  • +
  • CTC: IO=96, TIMER MODE=COUNTER, DIVISOR=18432, HI=256, LO=72, + INTERRUPTS ENABLED
  • +
+

Dyno Z180 SBC

+

The Dyno Computer is a Zilog Z180-based computer initially designed to +run Wayne Warthen’s ROMWBW

+ +

ROM Image File: DYNO_std.rom

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BusDyno•Bus
Default CPU Speed18.432 MHz
InterruptsMode 2
System TimerZ180
Serial Default38400 Baud
Memory ManagerZ180
ROM Size512 KB
RAM Size512 KB
+

Supported Hardware

+
    +
  • BQRTC: IO=80
  • +
  • ASCI: IO=192, INTERRUPTS ENABLED
  • +
  • ASCI: IO=193, INTERRUPTS ENABLED
  • +
  • MD: TYPE=RAM
  • +
  • MD: TYPE=ROM
  • +
  • FD: MODE=DYNO, IO=132, DRIVE 0, TYPE=3.5” HD
  • +
  • FD: MODE=DYNO, IO=132, DRIVE 1, TYPE=3.5” HD
  • +
  • PPIDE: IO=76, MASTER
  • +
  • PPIDE: IO=76, SLAVE
  • +
+

EP Mini-ITX Z180

+

EtchedPixels Z180 Mini-ITX. The SC126 was almost my ideal retrobrew +Z80/Z180 system but with a couple of niggles and lack of a convenient +case option. This is the same core Z180 CPU/RAM/ROM design taken the +other direction, of expandability.

+ +

ROM Image File: EPITX_std.rom

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BusRCBus + UEXT
Default CPU Speed18.432 MHz
InterruptsMode 2
System TimerZ180
Serial Default115200 Baud
Memory ManagerZ180
ROM Size512 KB
RAM Size512 KB
+

Supported Hardware

+
    +
  • INTRTC: ENABLED
  • +
  • ASCI: IO=192, INTERRUPTS ENABLED
  • +
  • ASCI: IO=193, INTERRUPTS ENABLED
  • +
  • UART: IO=160
  • +
  • UART: IO=168
  • +
  • TMS: MODE=MSX, IO=152, SCREEN=40X24, KEYBOARD=NONE
  • +
  • MD: TYPE=RAM
  • +
  • MD: TYPE=ROM
  • +
  • FD: MODE=EPFDC, IO=72, DRIVE 0, TYPE=3.5” HD
  • +
  • FD: MODE=EPFDC, IO=72, DRIVE 1, TYPE=3.5” HD
  • +
  • SD: MODE=EPITX, IO=66, UNITS=1
  • +
+

Easy/Tiny Z80

+

Easy Z80 SBC

+

This project is a simple, easy to understand, yet capable single board +computer. It reuses the same memory paging mechanism I’ve implemented in +Zeta SBC V2. It uses Zilog Z80 SIO/O and Z80 CTC peripheral ICs and +implements daisy chain mode 2 interrupt configuration

+

(Not to be confused with EaZy80)

+ +

ROM Image File: EZZ80_easy_std.rom

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BusRCBus
Default CPU Speed10.000 MHz
InterruptsMode 2
System TimerCTC
Serial Default115200 Baud
Memory ManagerZ2
ROM Size512 KB
RAM Size512 KB
+

Supported Hardware

+
    +
  • FP: LEDIO=0, SWIO=0
  • +
  • LCD: IO=218, SIZE=20X4
  • +
  • DSRTC: MODE=STD, IO=192
  • +
  • INTRTC: ENABLED
  • +
  • UART: IO=128
  • +
  • UART: IO=136
  • +
  • UART: IO=160
  • +
  • UART: IO=168
  • +
  • SIO MODE=STD, IO=128, CHANNEL A, INTERRUPTS ENABLED
  • +
  • SIO MODE=STD, IO=128, CHANNEL B, INTERRUPTS ENABLED
  • +
  • SIO MODE=RC, IO=132, CHANNEL A, INTERRUPTS ENABLED
  • +
  • SIO MODE=RC, IO=132, CHANNEL B, INTERRUPTS ENABLED
  • +
  • CH: IO=62
  • +
  • CH: IO=60
  • +
  • CHUSB: IO=62
  • +
  • CHUSB: IO=60
  • +
  • MD: TYPE=RAM
  • +
  • MD: TYPE=ROM
  • +
  • FD: MODE=RCWDC, IO=80, DRIVE 0, TYPE=3.5” HD
  • +
  • FD: MODE=RCWDC, IO=80, DRIVE 1, TYPE=3.5” HD
  • +
  • IDE: MODE=RC, IO=16, MASTER
  • +
  • IDE: MODE=RC, IO=16, SLAVE
  • +
  • PPIDE: IO=32, MASTER
  • +
  • PPIDE: IO=32, SLAVE
  • +
  • SD: MODE=PIO, IO=105, UNITS=1
  • +
  • CTC: IO=136, TIMER MODE=COUNTER, DIVISOR=18432, HI=256, LO=72, + INTERRUPTS ENABLED
  • +
+

Tiny Z80 SBC

+

Tiny Z80 is a business card sized (size?!) single board computer (SBC). +It is mostly compatible with Easy Z80, and offers similar capabilities +Tiny Z80 includes a USB to Serial converter IC on board connected to one +of the SIO ports, for ease of use with modern computers.

+
    +
  • Creator: Sergey Kiselev
  • +
  • Github: Tiny_Z80
  • +
+

ROM Image File: EZZ80_tiny_std.rom

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BusRCBus
Default CPU Speed16.000 MHz
InterruptsMode 2
System TimerCTC
Serial Default115200 Baud
Memory ManagerZ2
ROM Size512 KB
RAM Size512 KB
+

Supported Hardware

+
    +
  • FP: LEDIO=0, SWIO=0
  • +
  • LCD: IO=218, SIZE=20X4
  • +
  • DSRTC: MODE=STD, IO=192
  • +
  • INTRTC: ENABLED
  • +
  • UART: IO=128
  • +
  • UART: IO=136
  • +
  • UART: IO=160
  • +
  • UART: IO=168
  • +
  • SIO MODE=STD, IO=24, CHANNEL A, INTERRUPTS ENABLED
  • +
  • SIO MODE=STD, IO=24, CHANNEL B, INTERRUPTS ENABLED
  • +
  • SIO MODE=RC, IO=132, CHANNEL A, INTERRUPTS ENABLED
  • +
  • SIO MODE=RC, IO=132, CHANNEL B, INTERRUPTS ENABLED
  • +
  • CH: IO=62
  • +
  • CH: IO=60
  • +
  • CHUSB: IO=62
  • +
  • CHUSB: IO=60
  • +
  • MD: TYPE=RAM
  • +
  • MD: TYPE=ROM
  • +
  • FD: MODE=RCWDC, IO=80, DRIVE 0, TYPE=3.5” HD
  • +
  • FD: MODE=RCWDC, IO=80, DRIVE 1, TYPE=3.5” HD
  • +
  • IDE: MODE=RC, IO=144, MASTER
  • +
  • IDE: MODE=RC, IO=144, SLAVE
  • +
  • PPIDE: IO=32, MASTER
  • +
  • PPIDE: IO=32, SLAVE
  • +
  • SD: MODE=PIO, IO=105, UNITS=1
  • +
  • CTC: IO=16, TIMER MODE=COUNTER, DIVISOR=18432, HI=256, LO=72, + INTERRUPTS ENABLED
  • +
+

S100 Computers FPGA Z80 SBC

+

An FPGA Z80 based S100 SBC

+ +

ROM Image File: FZ80_std.rom

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BusS100
Default CPU Speed8.000 MHz
InterruptsNone
System TimerNone
Serial Default9600 Baud
Memory ManagerZ2
ROM Size0 KB
RAM Size512 KB
+

Supported Hardware

+
    +
  • FP: LEDIO=255
  • +
  • DS5RTC: RTCIO=104, IO=104
  • +
  • SSER: IO=52
  • +
  • LPT: MODE=S100, IO=199
  • +
  • FV: IO=192, KBD MODE=FV, KBD IO=3
  • +
  • KBD: ENABLED
  • +
  • SCON: IO=0
  • +
  • MD: TYPE=RAM
  • +
  • PPIDE: IO=48, MASTER
  • +
  • PPIDE: IO=48, SLAVE
  • +
  • SD: MODE=FZ80, IO=108, UNITS=2
  • +
+

Notes:

+
    +
  • Requires matching FPGA code
  • +
+

Genesis Z180 System

+

A Z180 based board with 512k ram, 512k rom, dual serial / parallel, RTC +and SD Card, based on the STD bus. This was inspired on Pulsar Little +Big board and some designs of Stephen Cousins

+ +

ROM Image File: GMZ180_std.rom

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BusSTD
Default CPU Speed18.432 MHz
InterruptsMode 2
System TimerZ180
Serial Default115200 Baud
Memory ManagerZ180
ROM Size512 KB
RAM Size512 KB
+

Supported Hardware

+
    +
  • GM7303: IO=48
  • +
  • DSRTC: MODE=STD, IO=132
  • +
  • INTRTC: ENABLED
  • +
  • ASCI: IO=192, INTERRUPTS ENABLED
  • +
  • ASCI: IO=193, INTERRUPTS ENABLED
  • +
  • MD: TYPE=RAM
  • +
  • MD: TYPE=ROM
  • +
  • IDE: MODE=GIDE, IO=32, MASTER
  • +
  • IDE: MODE=GIDE, IO=32, SLAVE
  • +
  • SD: MODE=GM, IO=132, UNITS=1
  • +
+

Heath H8 Z80 System

+

Turn your H8 into a RomWBW CP/M computer

+ +

ROM Image File: HEATH_std.rom

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BusH8
Default CPU Speed16.384 MHz
InterruptsMode 1
System TimerNone
Serial Default115200 Baud
Memory ManagerZ2
ROM Size512 KB
RAM Size512 KB
+

Supported Hardware

+
    +
  • H8P: IO=240
  • +
  • INTRTC: ENABLED
  • +
  • UART: IO=232
  • +
  • UART: IO=224
  • +
  • UART: IO=216
  • +
  • UART: IO=208
  • +
  • TMS: MODE=MSX, IO=152, SCREEN=80X24, KEYBOARD=NONE
  • +
  • MD: TYPE=RAM
  • +
  • MD: TYPE=ROM
  • +
  • FD: MODE=RCWDC, IO=80, DRIVE 0, TYPE=3.5” HD
  • +
  • FD: MODE=RCWDC, IO=80, DRIVE 1, TYPE=3.5” HD
  • +
  • PPIDE: IO=32, MASTER
  • +
  • PPIDE: IO=32, SLAVE
  • +
  • AY38910: MODE=MSX, IO=160, CLOCK=1789772 HZ
  • +
+

Z180 Mark IV SBC

+

The Z180 Mark IV is a single board computer, meaning it may run +stand-alone. It also has an interface to the RetroBrew bus (ECB) for +access to additional peripheral boards.

+ +

ROM Image File: MK4_std.rom

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BusECB
Default CPU Speed18.432 MHz
InterruptsMode 2
System TimerZ180
Serial Default38400 Baud
Memory ManagerZ180
ROM Size512 KB
RAM Size512 KB
+

Supported Hardware

+
    +
  • DSRTC: MODE=STD, IO=138
  • +
  • ASCI: IO=64, INTERRUPTS ENABLED
  • +
  • ASCI: IO=65, INTERRUPTS ENABLED
  • +
  • UART: IO=24
  • +
  • UART: IO=128
  • +
  • UART: IO=192
  • +
  • UART: IO=200
  • +
  • UART: IO=208
  • +
  • UART: IO=216
  • +
  • VGA: IO=224, KBD MODE=PS/2, KBD IO=224
  • +
  • CVDU: MODE=ECB, IO=224, KBD MODE=PS/2, KBD IO=226
  • +
  • KBD: ENABLED
  • +
  • PRP: IO=168
  • +
  • PRPCON: ENABLED
  • +
  • PRPSD: ENABLED
  • +
  • MD: TYPE=RAM
  • +
  • MD: TYPE=ROM
  • +
  • FD: MODE=DIDE, IO=42, DRIVE 0, TYPE=3.5” HD
  • +
  • FD: MODE=DIDE, IO=42, DRIVE 1, TYPE=3.5” HD
  • +
  • IDE: MODE=MK4, IO=128, MASTER
  • +
  • IDE: MODE=MK4, IO=128, SLAVE
  • +
  • SD: MODE=MK4, IO=137, UNITS=1
  • +
+

NABU w/ RomWBW Option Board

+

No modifications to the NABU motherboard needed. Leave the standard NABU +ROM in its socket on the motherboard, no need to remove it. You can +switch back to standard NABU mode by changing one jumper on the Option +Card

+ +

ROM Image File: NABU_std.rom

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BusNABU
Default CPU Speed3.580 MHz
InterruptsMode 2
System TimerTMS
Serial Default115200 Baud
Memory ManagerZ2
ROM Size512 KB
RAM Size512 KB
+

Supported Hardware

+
    +
  • NABU: IO=64
  • +
  • INTRTC: ENABLED
  • +
  • UART: IO=72
  • +
  • TMS: MODE=NABU, IO=160, SCREEN=80X24, KEYBOARD=NABU, INTERRUPTS + ENABLED
  • +
  • NABUKB: IO=144
  • +
  • MD: TYPE=RAM
  • +
  • MD: TYPE=ROM
  • +
  • PPIDE: IO=96, MASTER
  • +
  • PPIDE: IO=96, SLAVE
  • +
  • AY38910: MODE=NABU, IO=65, CLOCK=1789772 HZ
  • +
+

Notes:

+
    +
  • TMS video assumes F18A replacement for TMS9918
  • +
+

Nhyodyne Z80 MBC

+

Nhyodyne: A Modular Backplane Computer (MBC).

+

The purpose of this project is to revisit the design concepts behind my +original Z80 SBC (aka test prototype) which has evolved into the SBC +V2-005 over several years. Attempt to introduce some new concepts to +make the design more modular, flexible, and less expensive.

+

The MBC consists of four core boards: Z80 backplane, Z80 processor, Z80 +clock, and Z80 ROM. These are sufficient to build a working system of +minimum capability.

+ +

ROM Image File: MBC_std.rom

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BusMBC
Default CPU Speed8.000 MHz
InterruptsNone
System TimerNone
Serial Default38400 Baud
Memory ManagerMBC
ROM Size512 KB
RAM Size512 KB
+

Supported Hardware

+
    +
  • PKD: IO=96, SIZE=8X1
  • +
  • DSRTC: MODE=STD, IO=112
  • +
  • UART: IO=104
  • +
  • UART: IO=128
  • +
  • UART: IO=136
  • +
  • SIO MODE=ZP, IO=176, CHANNEL A
  • +
  • SIO MODE=ZP, IO=176, CHANNEL B
  • +
  • PIO: IO=184, CHANNEL A
  • +
  • PIO: IO=184, CHANNEL B
  • +
  • PIO: IO=188, CHANNEL A
  • +
  • PIO: IO=188, CHANNEL B
  • +
  • LPT: MODE=SPP, IO=232
  • +
  • CVDU: MODE=MBC, IO=224, KBD MODE=PS/2, KBD IO=226
  • +
  • TMS: MODE=MBC, IO=152, SCREEN=80X24, KEYBOARD=KBD
  • +
  • KBD: ENABLED
  • +
  • ESP: IO=156
  • +
  • ESPCON: ENABLED
  • +
  • ESPSER: DEVICE=0
  • +
  • ESPSER: DEVICE=1
  • +
  • MD: TYPE=RAM
  • +
  • MD: TYPE=ROM
  • +
  • FD: MODE=MBC, IO=48, DRIVE 0, TYPE=3.5” HD
  • +
  • FD: MODE=MBC, IO=48, DRIVE 1, TYPE=3.5” HD
  • +
  • PPIDE: IO=96, MASTER
  • +
  • PPIDE: IO=96, SLAVE
  • +
  • SPK: IO=112
  • +
+

RetroBrew Z80

+

RetroBrew Z80 SBC V2

+

The SBC V2 is a Zilog Z80 processor board. It’s a 100x160mm board that +is capable of functioning both as a standalone SBC or as attached to the +ECB bus.

+

Previously known as the N8VEM SBC, after Andrews Ham radio call sign, +development began in 2006 wth V1 and is currently still in development, +it launched a tsunami of developments based on the Euro Card Bus (ECB) +standard.

+ +

ROM Image File: SBC_std.rom

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BusECB
Default CPU Speed8.000 MHz
InterruptsNone
System TimerNone
Serial Default38400 Baud
Memory ManagerSBC
ROM Size512 KB
RAM Size512 KB
+

Supported Hardware

+
    +
  • DSRTC: MODE=STD, IO=112
  • +
  • UART: MODE=SBC, IO=104
  • +
  • UART: MODE=CAS, IO=128
  • +
  • UART: MODE=MFP, IO=104
  • +
  • UART: MODE=4UART, IO=192
  • +
  • UART: MODE=4UART, IO=200
  • +
  • UART: MODE=4UART, IO=208
  • +
  • UART: MODE=4UART, IO=216
  • +
  • VGA: IO=224, KBD MODE=PS/2, KBD IO=224
  • +
  • CVDU: MODE=ECB, IO=224, KBD MODE=PS/2, KBD IO=226
  • +
  • CVDU occupies 905 bytes.
  • +
  • KBD: ENABLED
  • +
  • PRP: IO=168
  • +
  • PRPCON: ENABLED
  • +
  • PRPSD: ENABLED
  • +
  • MD: TYPE=RAM
  • +
  • MD: TYPE=ROM
  • +
  • FD: MODE=DIO, IO=54, DRIVE 0, TYPE=3.5” HD
  • +
  • FD: MODE=DIO, IO=54, DRIVE 1, TYPE=3.5” HD
  • +
  • PPIDE: IO=96, MASTER
  • +
  • PPIDE: IO=96, SLAVE
  • +
+

RetroBrew Z80 SimH

+

Image for Altair Z80 SimH emulator

+

ROM Image File: SBC_simh.rom

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Bus-
Default CPU Speed8.000 MHz
InterruptsMode 1
System TimerSimH
Serial Default38400 Baud
Memory ManagerSBC
ROM Size512 KB
RAM Size512 KB
+

Supported Hardware

+
    +
  • SIMRTC: IO=254
  • +
  • SSER: IO=109
  • +
  • MD: TYPE=RAM
  • +
  • MD: TYPE=ROM
  • +
  • HDSK: IO=253, DEVICE COUNT=2
  • +
+

Notes:

+
    +
  • CPU speed and Serial configuration not relevant in emulator
  • +
+

N8 Z180 SBC

+

The N8 is intended to be a “home brew” style computer in the style of +early 1980’s all-in-one home computers with a usable set of features +such as color graphics, audio, an assortment of mass storage options, a +variety of ports, etc. Although a bus expansion is supported no +additional boards are required.

+

This configuration is for the N8-2312 and latter (4314) revisions

+ +

ROM Image File: N8_std.rom

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BusECB
Default CPU Speed18.432 MHz
InterruptsMode 2
System TimerZ180
Serial Default38400 Baud
Memory ManagerN8
ROM Size512 KB
RAM Size512 KB
+

Supported Hardware

+
    +
  • DSRTC: MODE=STD, IO=136
  • +
  • ASCI: IO=64, INTERRUPTS ENABLED
  • +
  • ASCI: IO=65, INTERRUPTS ENABLED
  • +
  • TMS: MODE=N8, IO=152, SCREEN=40X24, KEYBOARD=PPK
  • +
  • PPK: ENABLED
  • +
  • MD: TYPE=RAM
  • +
  • MD: TYPE=ROM
  • +
  • FD: MODE=N8, IO=140, DRIVE 0, TYPE=3.5” HD
  • +
  • FD: MODE=N8, IO=140, DRIVE 1, TYPE=3.5” HD
  • +
  • SD: MODE=CSIO, IO=136, UNITS=1
  • +
  • AY38910: MODE=N8, IO=156, CLOCK=1789772 HZ
  • +
+

Notes:

+
    +
  • SD Card interface is configured for CSIO (N8 date code >= 2312)
  • +
+

RCBus Z80

+

RCBus Z80 CPU Module

+

Generic Rom Image.

+

ROM Image File: RCZ80_std.rom

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BusRCBus
Default CPU Speed7.372 MHz
InterruptsMode 1
System TimerNone
Serial Default115200 Baud
Memory ManagerZ2
ROM Size512 KB
RAM Size512 KB
+

Supported Hardware

+
    +
  • FP: LEDIO=0, SWIO=0
  • +
  • LCD: IO=218, SIZE=20X4
  • +
  • DSRTC: MODE=STD, IO=192
  • +
  • UART: IO=128
  • +
  • UART: IO=136
  • +
  • UART: IO=160
  • +
  • UART: IO=168
  • +
  • SIO MODE=RC, IO=128, CHANNEL A, INTERRUPTS ENABLED
  • +
  • SIO MODE=RC, IO=128, CHANNEL B, INTERRUPTS ENABLED
  • +
  • SIO MODE=RC, IO=132, CHANNEL A, INTERRUPTS ENABLED
  • +
  • SIO MODE=RC, IO=132, CHANNEL B, INTERRUPTS ENABLED
  • +
  • ACIA: IO=128, INTERRUPTS ENABLED
  • +
  • CH: IO=62
  • +
  • CH: IO=60
  • +
  • CHUSB: IO=62
  • +
  • CHUSB: IO=60
  • +
  • MD: TYPE=RAM
  • +
  • MD: TYPE=ROM
  • +
  • FD: MODE=RCWDC, IO=80, DRIVE 0, TYPE=3.5” HD
  • +
  • FD: MODE=RCWDC, IO=80, DRIVE 1, TYPE=3.5” HD
  • +
  • IDE: MODE=RC, IO=16, MASTER
  • +
  • IDE: MODE=RC, IO=16, SLAVE
  • +
  • PPIDE: IO=32, MASTER
  • +
  • PPIDE: IO=32, SLAVE
  • +
  • SD: MODE=PIO, IO=105, UNITS=1
  • +
+

RCBus Z80 CPU Module (KIO)

+

Generic Rom Image. SIO Serial baud rate managed by CTC

+

ROM Image File: RCZ80_kio_std.rom

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BusRCBus
Default CPU Speed7.372 MHz
InterruptsMode 2
System TimerCTC
Serial Default115200 Baud
Memory ManagerZ2
ROM Size512 KB
RAM Size512 KB
+

Supported Hardware

+
    +
  • FP: LEDIO=0, SWIO=0
  • +
  • LCD: IO=218, SIZE=20X4
  • +
  • DSRTC: MODE=STD, IO=192
  • +
  • INTRTC: ENABLED
  • +
  • UART: IO=128
  • +
  • UART: IO=136
  • +
  • UART: IO=160
  • +
  • UART: IO=168
  • +
  • SIO MODE=STD, IO=136, CHANNEL A, INTERRUPTS ENABLED
  • +
  • SIO MODE=STD, IO=136, CHANNEL B, INTERRUPTS ENABLED
  • +
  • CH: IO=62
  • +
  • CH: IO=60
  • +
  • CHUSB: IO=62
  • +
  • CHUSB: IO=60
  • +
  • MD: TYPE=RAM
  • +
  • MD: TYPE=ROM
  • +
  • FD: MODE=RCWDC, IO=80, DRIVE 0, TYPE=3.5” HD
  • +
  • FD: MODE=RCWDC, IO=80, DRIVE 1, TYPE=3.5” HD
  • +
  • IDE: MODE=RC, IO=16, MASTER
  • +
  • IDE: MODE=RC, IO=16, SLAVE
  • +
  • PPIDE: IO=32, MASTER
  • +
  • PPIDE: IO=32, SLAVE
  • +
  • SD: MODE=PIO, IO=105, UNITS=1
  • +
  • KIO: IO=128
  • +
  • CTC: IO=132, TIMER MODE=TIMER/16, DIVISOR=9216, HI=256, LO=36, + INTERRUPTS ENABLED
  • +
+

Z80-512K CPU/RAM/ROM Module

+

Z80-512K is an RCBus and RC2014* compatible module, designed to run +RomWBW firmware including CP/M, ZSDOS, and various applications under +these OSes. Z80-512K combines functionality of CPU, RAM, and ROM on a +single module, thus saving space on the backplane.

+ +

ROM Image File: RCZ80_skz_std.rom

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BusRCBus
Default CPU Speed7.372 MHz
InterruptsMode 1
System TimerNone
Serial Default115200 Baud
Memory ManagerZ2
ROM Size512 KB
RAM Size512 KB
+

Supported Hardware

+
    +
  • FP: LEDIO=0, SWIO=0
  • +
  • LCD: IO=218, SIZE=20X4
  • +
  • DSRTC: MODE=STD, IO=192
  • +
  • UART: IO=128
  • +
  • UART: IO=136
  • +
  • UART: IO=160
  • +
  • UART: IO=168
  • +
  • SIO MODE=RC, IO=128, CHANNEL A, INTERRUPTS ENABLED
  • +
  • SIO MODE=RC, IO=128, CHANNEL B, INTERRUPTS ENABLED
  • +
  • SIO MODE=RC, IO=132, CHANNEL A, INTERRUPTS ENABLED
  • +
  • SIO MODE=RC, IO=132, CHANNEL B, INTERRUPTS ENABLED
  • +
  • ACIA: IO=128, INTERRUPTS ENABLED
  • +
  • CH: IO=62
  • +
  • CH: IO=60
  • +
  • CHUSB: IO=62
  • +
  • CHUSB: IO=60
  • +
  • MD: TYPE=RAM
  • +
  • MD: TYPE=ROM
  • +
  • FD: MODE=RCWDC, IO=80, DRIVE 0, TYPE=3.5” HD
  • +
  • FD: MODE=RCWDC, IO=80, DRIVE 1, TYPE=3.5” HD
  • +
  • IDE: MODE=RC, IO=16, MASTER
  • +
  • IDE: MODE=RC, IO=16, SLAVE
  • +
  • PPIDE: IO=32, MASTER
  • +
  • PPIDE: IO=32, SLAVE
  • +
  • SD: MODE=PIO, IO=105, UNITS=1
  • +
+

ZRC Z80 CPU Module

+

ZRC is derived from the ZoRC experiment. The basic notion is that large +RAM and fast serial upload enable a diskless CP/M SBC. However, just in +case that idea didn’t work out, ZRC has an optional compact flash +interface. The targeted software for ZRC is ROMWBW. ZRC physically +contains no ROM and 2MB of RAM.

+

In the STD configuration the first 512KB of RAM is loaded with a ROM +image from disk storage and then handled like ROM. Essentially, an area +of the RAM is reserved to act as ROM.

+ +

ROM Image File: RCZ80_zrc_std.rom

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BusRCBus
Default CPU Speed14.745 MHz
InterruptsMode 1
System TimerNone
Serial Default115200 Baud
Memory ManagerZRC
ROM Size512 KB
RAM Size1536 KB
+

Supported Hardware

+
    +
  • FP: LEDIO=0, SWIO=0
  • +
  • LCD: IO=218, SIZE=20X4
  • +
  • DSRTC: MODE=STD, IO=192
  • +
  • UART: IO=128
  • +
  • UART: IO=136
  • +
  • UART: IO=160
  • +
  • UART: IO=168
  • +
  • SIO MODE=RC, IO=128, CHANNEL A, INTERRUPTS ENABLED
  • +
  • SIO MODE=RC, IO=128, CHANNEL B, INTERRUPTS ENABLED
  • +
  • SIO MODE=RC, IO=132, CHANNEL A, INTERRUPTS ENABLED
  • +
  • SIO MODE=RC, IO=132, CHANNEL B, INTERRUPTS ENABLED
  • +
  • ACIA: IO=128, INTERRUPTS ENABLED
  • +
  • VRC: IO=0, KBD MODE=VRC, KBD IO=244
  • +
  • KBD: ENABLED
  • +
  • CH: IO=62
  • +
  • CH: IO=60
  • +
  • CHUSB: IO=62
  • +
  • CHUSB: IO=60
  • +
  • MD: TYPE=RAM
  • +
  • MD: TYPE=ROM
  • +
  • FD: MODE=RCWDC, IO=80, DRIVE 0, TYPE=3.5” HD
  • +
  • FD: MODE=RCWDC, IO=80, DRIVE 1, TYPE=3.5” HD
  • +
  • IDE: MODE=RC, IO=16, MASTER
  • +
  • IDE: MODE=RC, IO=16, SLAVE
  • +
  • PPIDE: IO=32, MASTER
  • +
  • PPIDE: IO=32, SLAVE
  • +
  • SD: MODE=PIO, IO=105, UNITS=1
  • +
+

ZRC Z80 CPU Module (RAM)

+

This profile differs (from STD) only in how the system boots, and how +RAM is configured. Boot occurs directly to RAM, loading HBIOS directly +from disk storage rather than via a pseudo ROM image copied into RAM.

+

A RAM disk is configured preloaded with files that would normally be on +the ROM disk. There is no ROM disk in this configuration.

+

The RAM config is the newer approach and provides a more efficient bank +layout. The intent to replace the STD config with the RAM config.

+
    +
  • Creator: Bill Shen
  • +
+

ROM Image File: RCZ80_zrc_ram_std.rom

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BusRCBus
Default CPU Speed14.745 MHz
InterruptsMode 1
System TimerNone
Serial Default115200 Baud
Memory ManagerZRC
ROM Size0 KB
RAM Size512 KB
+

Supported Hardware

+
    +
  • FP: LEDIO=0, SWIO=0
  • +
  • LCD: IO=218, SIZE=20X4
  • +
  • DSRTC: MODE=STD, IO=192
  • +
  • UART: IO=128
  • +
  • UART: IO=136
  • +
  • UART: IO=160
  • +
  • UART: IO=168
  • +
  • SIO MODE=RC, IO=128, CHANNEL A, INTERRUPTS ENABLED
  • +
  • SIO MODE=RC, IO=128, CHANNEL B, INTERRUPTS ENABLED
  • +
  • SIO MODE=RC, IO=132, CHANNEL A, INTERRUPTS ENABLED
  • +
  • SIO MODE=RC, IO=132, CHANNEL B, INTERRUPTS ENABLED
  • +
  • ACIA: IO=128, INTERRUPTS ENABLED
  • +
  • VRC: IO=0, KBD MODE=VRC, KBD IO=244
  • +
  • KBD: ENABLED
  • +
  • CH: IO=62
  • +
  • CH: IO=60
  • +
  • CHUSB: IO=62
  • +
  • CHUSB: IO=60
  • +
  • MD: TYPE=RAM
  • +
  • FD: MODE=RCWDC, IO=80, DRIVE 0, TYPE=3.5” HD
  • +
  • FD: MODE=RCWDC, IO=80, DRIVE 1, TYPE=3.5” HD
  • +
  • IDE: MODE=RC, IO=16, MASTER
  • +
  • IDE: MODE=RC, IO=16, SLAVE
  • +
  • PPIDE: IO=32, MASTER
  • +
  • PPIDE: IO=32, SLAVE
  • +
  • SD: MODE=PIO, IO=105, UNITS=1
  • +
+

ZRC512 Z80 CPU Module

+

ZRC512 is a faster and hobbyist-friendly variant of ZRC. It is designed +specifically for ROM-less RomWBW. HBIOS is loaded from disk at boot

+ +

ROM Image File: RCZ80_zrc512_std.rom

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BusRCBus
Default CPU Speed22.000 MHz
InterruptsMode 1
System TimerNone
Serial Default115200 Baud
Memory ManagerZRC
ROM Size0 KB
RAM Size512 KB
+

Supported Hardware

+
    +
  • FP: LEDIO=0, SWIO=0
  • +
  • LCD: IO=218, SIZE=20X4
  • +
  • DSRTC: MODE=STD, IO=192
  • +
  • UART: IO=128
  • +
  • UART: IO=136
  • +
  • UART: IO=160
  • +
  • UART: IO=168
  • +
  • SIO MODE=RC, IO=128, CHANNEL A, INTERRUPTS ENABLED
  • +
  • SIO MODE=RC, IO=128, CHANNEL B, INTERRUPTS ENABLED
  • +
  • SIO MODE=RC, IO=132, CHANNEL A, INTERRUPTS ENABLED
  • +
  • SIO MODE=RC, IO=132, CHANNEL B, INTERRUPTS ENABLED
  • +
  • ACIA: IO=128, INTERRUPTS ENABLED
  • +
  • VRC: IO=0, KBD MODE=VRC, KBD IO=244
  • +
  • KBD: ENABLED
  • +
  • CH: IO=62
  • +
  • CH: IO=60
  • +
  • CHUSB: IO=62
  • +
  • CHUSB: IO=60
  • +
  • MD: TYPE=RAM
  • +
  • FD: MODE=RCWDC, IO=80, DRIVE 0, TYPE=3.5” HD
  • +
  • FD: MODE=RCWDC, IO=80, DRIVE 1, TYPE=3.5” HD
  • +
  • IDE: MODE=RC, IO=16, MASTER
  • +
  • IDE: MODE=RC, IO=16, SLAVE
  • +
  • PPIDE: IO=32, MASTER
  • +
  • PPIDE: IO=32, SLAVE
  • +
  • SD: MODE=PIO, IO=105, UNITS=1
  • +
+

EaZy80-512 Z80 CPU Module

+

Eazy80-512 is Eazy80 rev2 pc board configured with 512K RAM to run +RomWBW. The design was derived from modifications to Eazy80 Rev1 that +supported RomWBW.

+

HBIOS is loaded from disk at boot by ROM monitor

+

(Not to be confused with EasyZ80)

+ +

ROM Image File: RCZ80_ez512_std.rom

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BusRCBus
Default CPU Speed22.000 MHz
InterruptsMode 2
System TimerNone
Serial Default115200 Baud
Memory ManagerEZ512
ROM Size0 KB
RAM Size512 KB
+

Supported Hardware

+
    +
  • DSRTC: MODE=STD, IO=192
  • +
  • SIO MODE=STD, IO=8, CHANNEL A, INTERRUPTS ENABLED
  • +
  • SIO MODE=STD, IO=8, CHANNEL B, INTERRUPTS ENABLED
  • +
  • MD: TYPE=RAM
  • +
  • MD occupies 409 bytes.
  • +
  • SD: MODE=EZ512, IO=2, UNITS=1
  • +
  • KIO: IO=0
  • +
  • CTC: IO=4
  • +
+

K80W Z80 CPU Module

+

K80W is similar to K80. It is a 22MHz Z80 SBC with KIO (Z84C90) as the +I/O device. It is designed to run RomWBW. The current version is rev 2.1 +replacing the older K80W rev 1

+ +

ROM Image File: RCZ80_k80w_std.rom

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BusRCBus
Default CPU Speed22.000 MHz
InterruptsMode 2
System TimerNone
Serial Default115200 Baud
Memory ManagerZ2
ROM Size512 KB
RAM Size512 KB
+

Supported Hardware

+
    +
  • FP: LEDIO=0, SWIO=0
  • +
  • LCD: IO=218, SIZE=20X4
  • +
  • DSRTC: MODE=K80W, IO=192
  • +
  • UART: IO=128
  • +
  • UART: IO=136
  • +
  • UART: IO=160
  • +
  • UART: IO=168
  • +
  • SIO MODE=STD, IO=136, CHANNEL A, INTERRUPTS ENABLED
  • +
  • SIO MODE=STD, IO=136, CHANNEL B, INTERRUPTS ENABLED
  • +
  • VRC: IO=0, KBD MODE=VRC, KBD IO=244
  • +
  • KBD: ENABLED
  • +
  • CH: IO=62
  • +
  • CH: IO=60
  • +
  • CHUSB: IO=62
  • +
  • CHUSB: IO=60
  • +
  • MD: TYPE=RAM
  • +
  • MD: TYPE=ROM
  • +
  • FD: MODE=RCWDC, IO=80, DRIVE 0, TYPE=3.5” HD
  • +
  • FD: MODE=RCWDC, IO=80, DRIVE 1, TYPE=3.5” HD
  • +
  • IDE: MODE=RC, IO=16, MASTER
  • +
  • IDE: MODE=RC, IO=16, SLAVE
  • +
  • PPIDE: IO=32, MASTER
  • +
  • PPIDE: IO=32, SLAVE
  • +
  • SD: MODE=EZ512, IO=130, UNITS=1
  • +
  • KIO: IO=128
  • +
  • CTC: IO=132
  • +
+

RCBus Z180

+

RCBus Z180 CPU Module (External)

+

Generic Rom Image. For use with Z2 bank switched memory board (Z2 +external memory management)

+

ROM Image File: RCZ180_ext_std.rom

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BusRCBus
Default CPU Speed18.432 MHz
InterruptsMode 2
System TimerZ180
Serial Default115200 Baud
Memory ManagerZ2
ROM Size512 KB
RAM Size512 KB
+

Supported Hardware

+
    +
  • FP: LEDIO=0, SWIO=0
  • +
  • DSRTC: MODE=STD, IO=12
  • +
  • INTRTC: ENABLED
  • +
  • ASCI: IO=192, INTERRUPTS ENABLED
  • +
  • ASCI: IO=193, INTERRUPTS ENABLED
  • +
  • UART: IO=128
  • +
  • UART: IO=136
  • +
  • UART: IO=160
  • +
  • UART: IO=168
  • +
  • SIO MODE=RC, IO=128, CHANNEL A, INTERRUPTS ENABLED
  • +
  • SIO MODE=RC, IO=128, CHANNEL B, INTERRUPTS ENABLED
  • +
  • SIO MODE=RC, IO=132, CHANNEL A, INTERRUPTS ENABLED
  • +
  • SIO MODE=RC, IO=132, CHANNEL B, INTERRUPTS ENABLED
  • +
  • CH: IO=62
  • +
  • CH: IO=60
  • +
  • CHUSB: IO=62
  • +
  • CHUSB: IO=60
  • +
  • MD: TYPE=RAM
  • +
  • MD: TYPE=ROM
  • +
  • FD: MODE=RCWDC, IO=80, DRIVE 0, TYPE=3.5” HD
  • +
  • FD: MODE=RCWDC, IO=80, DRIVE 1, TYPE=3.5” HD
  • +
  • IDE: MODE=RC, IO=16, MASTER
  • +
  • IDE: MODE=RC, IO=16, SLAVE
  • +
  • PPIDE: IO=32, MASTER
  • +
  • PPIDE: IO=32, SLAVE
  • +
  • SD: MODE=PIO, IO=105, UNITS=1
  • +
+

RCBus Z180 CPU Module (Native)

+

Generic Rom Image. For use with linear memory board (Z180 native memory +management)

+

ROM Image File: RCZ180_nat_std.rom

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BusRCBus
Default CPU Speed18.432 MHz
InterruptsMode 2
System TimerZ180
Serial Default115200 Baud
Memory ManagerZ180
ROM Size512 KB
RAM Size512 KB
+

Supported Hardware

+
    +
  • FP: LEDIO=0, SWIO=0
  • +
  • DSRTC: MODE=STD, IO=12
  • +
  • INTRTC: ENABLED
  • +
  • ASCI: IO=192, INTERRUPTS ENABLED
  • +
  • ASCI: IO=193, INTERRUPTS ENABLED
  • +
  • UART: IO=128
  • +
  • UART: IO=136
  • +
  • UART: IO=160
  • +
  • UART: IO=168
  • +
  • SIO MODE=RC, IO=128, CHANNEL A, INTERRUPTS ENABLED
  • +
  • SIO MODE=RC, IO=128, CHANNEL B, INTERRUPTS ENABLED
  • +
  • SIO MODE=RC, IO=132, CHANNEL A, INTERRUPTS ENABLED
  • +
  • SIO MODE=RC, IO=132, CHANNEL B, INTERRUPTS ENABLED
  • +
  • CH: IO=62
  • +
  • CH: IO=60
  • +
  • CHUSB: IO=62
  • +
  • CHUSB: IO=60
  • +
  • MD: TYPE=RAM
  • +
  • MD: TYPE=ROM
  • +
  • FD: MODE=RCWDC, IO=80, DRIVE 0, TYPE=3.5” HD
  • +
  • FD: MODE=RCWDC, IO=80, DRIVE 1, TYPE=3.5” HD
  • +
  • IDE: MODE=RC, IO=16, MASTER
  • +
  • IDE: MODE=RC, IO=16, SLAVE
  • +
  • PPIDE: IO=32, MASTER
  • +
  • PPIDE: IO=32, SLAVE
  • +
  • SD: MODE=PIO, IO=105, UNITS=1
  • +
+

Z1RCC Z180 CPU Module

+

Z1RCC is a 2“x4” RomWBW-capable Z180 SBC.

+

Z1RCC has no flash memory on board but has a small (64 bytes) bootstrap +ROM in CPLD so that Z180 boots from this bootstrap ROM, copies a loader +from CF disk to top 32K of RAM, runs the loader to bring in the 480K +RomWBW image from CF disk, then start RomWBW from 0x0

+ +

ROM Image File: RCZ180_z1rcc_std.rom

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BusRCBus
Default CPU Speed18.432 MHz
InterruptsMode 2
System TimerZ180
Serial Default115200 Baud
Memory ManagerZ180
ROM Size0 KB
RAM Size512 KB
+

Supported Hardware

+
    +
  • FP: LEDIO=0, SWIO=0
  • +
  • DSRTC: MODE=STD, IO=12
  • +
  • INTRTC: ENABLED
  • +
  • ASCI: IO=192, INTERRUPTS ENABLED
  • +
  • ASCI: IO=193, INTERRUPTS ENABLED
  • +
  • UART: IO=128
  • +
  • UART: IO=136
  • +
  • UART: IO=160
  • +
  • UART: IO=168
  • +
  • SIO MODE=RC, IO=128, CHANNEL A, INTERRUPTS ENABLED
  • +
  • SIO MODE=RC, IO=128, CHANNEL B, INTERRUPTS ENABLED
  • +
  • SIO MODE=RC, IO=132, CHANNEL A, INTERRUPTS ENABLED
  • +
  • SIO MODE=RC, IO=132, CHANNEL B, INTERRUPTS ENABLED
  • +
  • CH: IO=62
  • +
  • CH: IO=60
  • +
  • CHUSB: IO=62
  • +
  • CHUSB: IO=60
  • +
  • MD: TYPE=RAM
  • +
  • FD: MODE=RCWDC, IO=80, DRIVE 0, TYPE=3.5” HD
  • +
  • FD: MODE=RCWDC, IO=80, DRIVE 1, TYPE=3.5” HD
  • +
  • IDE: MODE=RC, IO=16, MASTER
  • +
  • IDE: MODE=RC, IO=16, SLAVE
  • +
  • PPIDE: IO=32, MASTER
  • +
  • PPIDE: IO=32, SLAVE
  • +
  • SD: MODE=PIO, IO=105, UNITS=1
  • +
+

RCBus Z280

+

RCBus Z280 CPU Module (External)

+

Generic Rom Image. For use with Z2 bank switched memory board (Z2 +external memory management)

+

ROM Image File: RCZ280_ext_std.rom

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BusRCBus
Default CPU Speed12.000 MHz
InterruptsMode 1
System TimerNone
Serial Default115200 Baud
Memory ManagerZ2
ROM Size512 KB
RAM Size512 KB
+

Supported Hardware

+
    +
  • FP: LEDIO=0, SWIO=0
  • +
  • LCD: IO=218, SIZE=20X4
  • +
  • DSRTC: MODE=STD, IO=192
  • +
  • INTRTC: ENABLED
  • +
  • Z2U: IO=16
  • +
  • UART: IO=128
  • +
  • UART: IO=136
  • +
  • UART: IO=160
  • +
  • UART: IO=168
  • +
  • SIO MODE=RC, IO=128, CHANNEL A, INTERRUPTS ENABLED
  • +
  • SIO MODE=RC, IO=128, CHANNEL B, INTERRUPTS ENABLED
  • +
  • SIO MODE=RC, IO=132, CHANNEL A, INTERRUPTS ENABLED
  • +
  • SIO MODE=RC, IO=132, CHANNEL B, INTERRUPTS ENABLED
  • +
  • ACIA: IO=128, INTERRUPTS ENABLED
  • +
  • CH: IO=62
  • +
  • CH: IO=60
  • +
  • CHUSB: IO=62
  • +
  • CHUSB: IO=60
  • +
  • MD: TYPE=RAM
  • +
  • MD: TYPE=ROM
  • +
  • FD: MODE=RCWDC, IO=80, DRIVE 0, TYPE=3.5” HD
  • +
  • FD: MODE=RCWDC, IO=80, DRIVE 1, TYPE=3.5” HD
  • +
  • IDE: MODE=RC, IO=16, MASTER
  • +
  • IDE: MODE=RC, IO=16, SLAVE
  • +
  • PPIDE: IO=32, MASTER
  • +
  • PPIDE: IO=32, SLAVE
  • +
  • SD: MODE=PIO, IO=105, UNITS=1
  • +
+

RCBus Z280 CPU Module (Native)

+

Generic Rom Image. For use with linear memory board (Z280 native memory +management)

+

ROM Image File: RCZ280_nat_std.rom

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BusRCBus
Default CPU Speed12.000 MHz
InterruptsMode 3
System TimerZ280
Serial Default115200 Baud
Memory ManagerZ280
ROM Size512 KB
RAM Size512 KB
+

Supported Hardware

+
    +
  • FP: LEDIO=0, SWIO=0
  • +
  • LCD: IO=218, SIZE=20X4
  • +
  • DSRTC: MODE=STD, IO=192
  • +
  • INTRTC: ENABLED
  • +
  • Z2U: IO=16, INTERRUPTS ENABLED
  • +
  • UART: IO=128
  • +
  • UART: IO=136
  • +
  • UART: IO=160
  • +
  • UART: IO=168
  • +
  • SIO MODE=RC, IO=128, CHANNEL A, INTERRUPTS ENABLED
  • +
  • SIO MODE=RC, IO=128, CHANNEL B, INTERRUPTS ENABLED
  • +
  • SIO MODE=RC, IO=132, CHANNEL A, INTERRUPTS ENABLED
  • +
  • SIO MODE=RC, IO=132, CHANNEL B, INTERRUPTS ENABLED
  • +
  • CH: IO=62
  • +
  • CH: IO=60
  • +
  • CHUSB: IO=62
  • +
  • CHUSB: IO=60
  • +
  • MD: TYPE=RAM
  • +
  • MD: TYPE=ROM
  • +
  • FD: MODE=RCWDC, IO=80, DRIVE 0, TYPE=3.5” HD
  • +
  • FD: MODE=RCWDC, IO=80, DRIVE 1, TYPE=3.5” HD
  • +
  • IDE: MODE=RC, IO=16, MASTER
  • +
  • IDE: MODE=RC, IO=16, SLAVE
  • +
  • PPIDE: IO=32, MASTER
  • +
  • PPIDE: IO=32, SLAVE
  • +
  • SD: MODE=PIO, IO=105, UNITS=1
  • +
+

ZZRCC Z280 CPU Module

+

ZZRCC follows the basic concept of ZRCC that uses a small CPLD to +bootstrap from CF disk. Because Z280 has a native serial-bootstrap +capability, the CPLD is even simpler than that of ZRCC. ZZRCC is Z280 +operating in Z80-compatible mode. It is designed for RC2014 bus ZZRCC +actually contains no ROM and 512KB of RAM.

+

In the STD configuration the first 256KB of RAM is loaded with a ROM +image from disk storage and then handled like ROM. Essentially, an area +of the RAM is reserved to act as ROM.

+ +

ROM Image File: RCZ280_zzrcc_std.rom

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BusRCBus
Default CPU Speed14.745 MHz
InterruptsMode 3
System TimerZ280
Serial Default115200 Baud
Memory ManagerZ280
ROM Size256 KB
RAM Size256 KB
+

Supported Hardware

+
    +
  • FP: LEDIO=0, SWIO=0
  • +
  • LCD: IO=218, SIZE=20X4
  • +
  • DSRTC: MODE=STD, IO=192
  • +
  • INTRTC: ENABLED
  • +
  • Z2U: IO=16, INTERRUPTS ENABLED
  • +
  • UART: IO=128
  • +
  • UART: IO=136
  • +
  • UART: IO=160
  • +
  • UART: IO=168
  • +
  • SIO MODE=RC, IO=128, CHANNEL A, INTERRUPTS ENABLED
  • +
  • SIO MODE=RC, IO=128, CHANNEL B, INTERRUPTS ENABLED
  • +
  • SIO MODE=RC, IO=132, CHANNEL A, INTERRUPTS ENABLED
  • +
  • SIO MODE=RC, IO=132, CHANNEL B, INTERRUPTS ENABLED
  • +
  • VRC: IO=0, KBD MODE=VRC, KBD IO=244
  • +
  • KBD: ENABLED
  • +
  • CH: IO=62
  • +
  • CH: IO=60
  • +
  • CHUSB: IO=62
  • +
  • CHUSB: IO=60
  • +
  • MD: TYPE=RAM
  • +
  • MD: TYPE=ROM
  • +
  • FD: MODE=RCWDC, IO=80, DRIVE 0, TYPE=3.5” HD
  • +
  • FD: MODE=RCWDC, IO=80, DRIVE 1, TYPE=3.5” HD
  • +
  • IDE: MODE=RC, IO=16, MASTER
  • +
  • IDE: MODE=RC, IO=16, SLAVE
  • +
  • PPIDE: IO=32, MASTER
  • +
  • PPIDE: IO=32, SLAVE
  • +
+

ZZRCC Z280 CPU Module (RAM)

+

This profile differs (from STD) only in how the system boots, and how +RAM is configured. Boot occurs directly to RAM, loading HBIOS directly +from disk storage rather than via a pseudo ROM image copied into RAM.

+

A RAM disk is configured preloaded with files that would normally be on +the ROM disk. There is no ROM disk in this configuration.

+

The RAM config is the newer approach and provides a more efficient bank +layout. The intent to replace the STD config with the RAM config.

+
    +
  • Creator: Bill Shen
  • +
+

ROM Image File: RCZ280_zzrcc_ram_std.rom

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BusRCBus
Default CPU Speed14.745 MHz
InterruptsMode 3
System TimerZ280
Serial Default115200 Baud
Memory ManagerZ280
ROM Size0 KB
RAM Size512 KB
+

Supported Hardware

+
    +
  • FP: LEDIO=0, SWIO=0
  • +
  • LCD: IO=218, SIZE=20X4
  • +
  • DSRTC: MODE=STD, IO=192
  • +
  • INTRTC: ENABLED
  • +
  • Z2U: IO=16, INTERRUPTS ENABLED
  • +
  • UART: IO=128
  • +
  • UART: IO=136
  • +
  • UART: IO=160
  • +
  • UART: IO=168
  • +
  • SIO MODE=RC, IO=128, CHANNEL A, INTERRUPTS ENABLED
  • +
  • SIO MODE=RC, IO=128, CHANNEL B, INTERRUPTS ENABLED
  • +
  • SIO MODE=RC, IO=132, CHANNEL A, INTERRUPTS ENABLED
  • +
  • SIO MODE=RC, IO=132, CHANNEL B, INTERRUPTS ENABLED
  • +
  • VRC: IO=0, KBD MODE=VRC, KBD IO=244
  • +
  • KBD: ENABLED
  • +
  • CH: IO=62
  • +
  • CH: IO=60
  • +
  • CHUSB: IO=62
  • +
  • CHUSB: IO=60
  • +
  • MD: TYPE=RAM
  • +
  • FD: MODE=RCWDC, IO=80, DRIVE 0, TYPE=3.5” HD
  • +
  • FD: MODE=RCWDC, IO=80, DRIVE 1, TYPE=3.5” HD
  • +
  • IDE: MODE=RC, IO=16, MASTER
  • +
  • IDE: MODE=RC, IO=16, SLAVE
  • +
  • PPIDE: IO=32, MASTER
  • +
  • PPIDE: IO=32, SLAVE
  • +
+

ZZ80MB Z280 SBC

+

ZZ80MB is a Z280-based motherboard with RC2014 expansion slots. It is +based on the ZZ80RC-CF design, but with two additional expansion slots +added. ZZ80MB is designed with an EPROM programmer function such that it +can boot from serial port, load EPROM programming image through the +serial port and program an EPROM. This feature can be used to program +EPROM for other computers

+ +

ROM Image File: RCZ280_zz80mb_std.rom

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BusRCBus
Default CPU Speed12.000 MHz
InterruptsMode 3
System TimerZ280
Serial Default115200 Baud
Memory ManagerZ280
ROM Size512 KB
RAM Size512 KB
+

Supported Hardware

+
    +
  • FP: LEDIO=0, SWIO=0
  • +
  • LCD: IO=218, SIZE=20X4
  • +
  • DSRTC: MODE=STD, IO=192
  • +
  • INTRTC: ENABLED
  • +
  • Z2U: IO=16, INTERRUPTS ENABLED
  • +
  • UART: IO=128
  • +
  • UART: IO=136
  • +
  • UART: IO=160
  • +
  • UART: IO=168
  • +
  • SIO MODE=RC, IO=128, CHANNEL A, INTERRUPTS ENABLED
  • +
  • SIO MODE=RC, IO=128, CHANNEL B, INTERRUPTS ENABLED
  • +
  • SIO MODE=RC, IO=132, CHANNEL A, INTERRUPTS ENABLED
  • +
  • SIO MODE=RC, IO=132, CHANNEL B, INTERRUPTS ENABLED
  • +
  • VRC: IO=0, KBD MODE=VRC, KBD IO=244
  • +
  • KBD: ENABLED
  • +
  • CH: IO=62
  • +
  • CH: IO=60
  • +
  • CHUSB: IO=62
  • +
  • CHUSB: IO=60
  • +
  • MD: TYPE=RAM
  • +
  • MD: TYPE=ROM
  • +
  • FD: MODE=RCWDC, IO=80, DRIVE 0, TYPE=3.5” HD
  • +
  • FD: MODE=RCWDC, IO=80, DRIVE 1, TYPE=3.5” HD
  • +
  • IDE: MODE=RC, IO=16, MASTER
  • +
  • IDE: MODE=RC, IO=16, SLAVE
  • +
  • PPIDE: IO=32, MASTER
  • +
  • PPIDE: IO=32, SLAVE
  • +
+

eZ80 for RCBus Module

+

The eZ80 for RCBus/RC2014 is a module designed for the RCBus and RC2014 +backplanes.

+

Its designed as a ‘compatible upgrade’ to the stock Z80 CPU. The eZ80 is +a CPU that was first released by Zilog about 20 years ago, and still +available from the manufacturer today

+ +

ROM Image File: RCEZ80_std.rom

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BusRCBus
Default CPU Speed20.000 MHz
InterruptsMode 1
System TimerEZ80
Serial Default115200 Baud
Memory ManagerZ2
ROM Size512 KB
RAM Size512 KB
+

Supported Hardware

+
    +
  • FP: LEDIO=0, SWIO=0
  • +
  • LCD: IO=218, SIZE=20X4
  • +
  • CH: IO=62
  • +
  • CH: IO=60
  • +
  • CHUSB: IO=62
  • +
  • CHUSB: IO=60
  • +
  • MD: TYPE=RAM
  • +
  • MD: TYPE=ROM
  • +
  • FD: MODE=RCWDC, IO=80, DRIVE 0, TYPE=3.5” HD
  • +
  • FD: MODE=RCWDC, IO=80, DRIVE 1, TYPE=3.5” HD
  • +
  • IDE: MODE=RC, IO=16, MASTER
  • +
  • IDE: MODE=RC, IO=16, SLAVE
  • +
  • PPIDE: IO=32, MASTER
  • +
  • PPIDE: IO=32, SLAVE
  • +
  • EZ80: CPU DRIVER
  • +
  • EZ80: SYS TIMER DRIVER
  • +
  • EZ80: RTC DRIVER
  • +
  • EZ80: UART DRIVER
  • +
+

Rhyophyre Z180 SBC

+

Single Board Computer featuring Zilog Z180 processor and NEC µPD7220 +Graphics Display Controller

+ +

ROM Image File: RPH_std.rom

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Bus-
Default CPU Speed18.432 MHz
InterruptsNone
System TimerNone
Serial Default38400 Baud
Memory ManagerRPH
ROM Size512 KB
RAM Size512 KB
+

Supported Hardware

+
    +
  • DSRTC: MODE=STD, IO=132
  • +
  • ASCI: IO=64
  • +
  • ASCI: IO=65
  • +
  • GDC: MODE=RPH, DISPLAY=EGA, IO=144
  • +
  • KBD: ENABLED
  • +
  • MD: TYPE=RAM
  • +
  • MD: TYPE=ROM
  • +
  • PPIDE: IO=136, MASTER
  • +
  • PPIDE: IO=136, SLAVE
  • +
+

S100 Computers Z180 SBC

+

A Z180 board which contains a flash RAM, a USB port interface and an SD +Card that can immediately boot up CPM. While it is on an S100 Bus board, +initially that board has only 8 significant chips and works as a self +contained computer outside the bus with a simple 9V power supply.

+

Later on it can be built up further with more chips, placed in an S100 +bus and one by one programed to interface with the 100’s of S100 bus +cards that are out there. It can in fact behave as a S100 bus master or +slave as defined by the IEEE-696 specs.

+ +

ROM Image File: S100_std.rom

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BusS100
Default CPU Speed18.432 MHz
InterruptsMode 2
System TimerZ180
Serial Default57600 Baud
Memory ManagerZ180
ROM Size512 KB
RAM Size512 KB
+

Supported Hardware

+
    +
  • INTRTC: ENABLED
  • +
  • ASCI: IO=192, INTERRUPTS ENABLED
  • +
  • ASCI: IO=193, INTERRUPTS ENABLED
  • +
  • SCON: IO=0
  • +
  • MD: TYPE=RAM
  • +
  • MD: TYPE=ROM
  • +
  • SD: MODE=SC, IO=12, UNITS=1
  • +
+

Notes:

+
    +
  • Z180 SBC SW2 (IOBYTE) Dip Switches:
  • +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BitSettingFunction
0OffUse Z180 ASCI Channel A for console
OnUse Propeller Console
1OffBoot to RomWBW Boot Loader
OnBoot to S100 Monitor
+

Small Computer Central Z180

+

Small Computer Central provides an extensive range hardware based around +the Zilog ecosystem. This section lists configurations specifically for +the Z180 processor

+

If you are using a Z80 processor you will probably be using the general +RCZ80_std configuration - RCBus Z80 CPU +Module. However, please consult Firmware, +RomWBW, +RCZ80_std +for further information and to ensure compatibility with your Z80 +system.

+ +

SC126 Z180 SBC

+

SC126 is a Z180 Motherboard.

+ +

ROM Image File: SCZ180_sc126_std.rom

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BusBP80
Default CPU Speed18.432 MHz
InterruptsMode 2
System TimerZ180
Serial Default115200 Baud
Memory ManagerZ180
ROM Size512 KB
RAM Size512 KB
+

Supported Hardware

+
    +
  • FP: LEDIO=13, SWIO=0
  • +
  • DSRTC: MODE=STD, IO=12
  • +
  • ASCI: IO=192, INTERRUPTS ENABLED
  • +
  • ASCI: IO=193, INTERRUPTS ENABLED
  • +
  • UART: IO=128
  • +
  • UART: IO=136
  • +
  • UART: IO=160
  • +
  • UART: IO=168
  • +
  • SIO MODE=RC, IO=128, CHANNEL A, INTERRUPTS ENABLED
  • +
  • SIO MODE=RC, IO=128, CHANNEL B, INTERRUPTS ENABLED
  • +
  • SIO MODE=RC, IO=132, CHANNEL A, INTERRUPTS ENABLED
  • +
  • SIO MODE=RC, IO=132, CHANNEL B, INTERRUPTS ENABLED
  • +
  • CH: IO=62
  • +
  • CH: IO=60
  • +
  • CHUSB: IO=62
  • +
  • CHUSB: IO=60
  • +
  • MD: TYPE=RAM
  • +
  • MD: TYPE=ROM
  • +
  • FD: MODE=RCWDC, IO=80, DRIVE 0, TYPE=3.5” HD
  • +
  • FD: MODE=RCWDC, IO=80, DRIVE 1, TYPE=3.5” HD
  • +
  • IDE: MODE=RC, IO=16, MASTER
  • +
  • IDE: MODE=RC, IO=16, SLAVE
  • +
  • PPIDE: IO=32, MASTER
  • +
  • PPIDE: IO=32, SLAVE
  • +
  • SD: MODE=SC, IO=12, UNITS=1
  • +
+

Notes:

+
    +
  • When disabled, watchdog requires /IM to be pulsed. If an RCBus module + holds the CPU in WAIT for more than this, the watchdog will fire when + disabled with random consequences. The Pico SD does this at power-on.
  • +
+

SC130 Z180 SBC

+

SC130 is an entry-level Z180 Motherboard designed primarily to run +RomWBW (and CP/M)

+ +

ROM Image File: SCZ180_sc130_std.rom

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BusRCBus
Default CPU Speed18.432 MHz
InterruptsMode 2
System TimerZ180
Serial Default115200 Baud
Memory ManagerZ180
ROM Size512 KB
RAM Size512 KB
+

Supported Hardware

+
    +
  • FP: LEDIO=0, SWIO=0
  • +
  • DSRTC: MODE=STD, IO=12
  • +
  • INTRTC: ENABLED
  • +
  • ASCI: IO=192, INTERRUPTS ENABLED
  • +
  • ASCI: IO=193, INTERRUPTS ENABLED
  • +
  • UART: IO=128
  • +
  • UART: IO=136
  • +
  • UART: IO=160
  • +
  • UART: IO=168
  • +
  • SIO MODE=RC, IO=128, CHANNEL A, INTERRUPTS ENABLED
  • +
  • SIO MODE=RC, IO=128, CHANNEL B, INTERRUPTS ENABLED
  • +
  • SIO MODE=RC, IO=132, CHANNEL A, INTERRUPTS ENABLED
  • +
  • SIO MODE=RC, IO=132, CHANNEL B, INTERRUPTS ENABLED
  • +
  • CH: IO=62
  • +
  • CH: IO=60
  • +
  • CHUSB: IO=62
  • +
  • CHUSB: IO=60
  • +
  • MD: TYPE=RAM
  • +
  • MD: TYPE=ROM
  • +
  • FD: MODE=RCWDC, IO=80, DRIVE 0, TYPE=3.5” HD
  • +
  • FD: MODE=RCWDC, IO=80, DRIVE 1, TYPE=3.5” HD
  • +
  • IDE: MODE=RC, IO=16, MASTER
  • +
  • IDE: MODE=RC, IO=16, SLAVE
  • +
  • PPIDE: IO=32, MASTER
  • +
  • PPIDE: IO=32, SLAVE
  • +
  • SD: MODE=SC, IO=12, UNITS=1
  • +
+

SC131 Z180 Pocket Comp

+

SC131 is a pocket-sized Z180 RomWBW CP/M computer.

+ +

ROM Image File: SCZ180_sc131_std.rom

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Bus-
Default CPU Speed18.432 MHz
InterruptsMode 2
System TimerZ180
Serial Default115200 Baud
Memory ManagerZ180
ROM Size512 KB
RAM Size512 KB
+

Supported Hardware

+
    +
  • INTRTC: ENABLED
  • +
  • ASCI: IO=192, INTERRUPTS ENABLED
  • +
  • ASCI: IO=193, INTERRUPTS ENABLED
  • +
  • MD: TYPE=RAM
  • +
  • MD: TYPE=ROM
  • +
  • SD: MODE=SC, IO=12, UNITS=1
  • +
+

SC140 Z180 CPU Module

+

SC140 is a Z180 SBC / Z50Bus Card card.

+ +

ROM Image File: SCZ180_sc140_std.rom

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BusZ50
Default CPU Speed18.432 MHz
InterruptsMode 2
System TimerZ180
Serial Default115200 Baud
Memory ManagerZ180
ROM Size512 KB
RAM Size512 KB
+

Supported Hardware

+
    +
  • FP: LEDIO=160, SWIO=160
  • +
  • DSRTC: MODE=STD, IO=12
  • +
  • INTRTC: ENABLED
  • +
  • ASCI: IO=192, INTERRUPTS ENABLED
  • +
  • ASCI: IO=193, INTERRUPTS ENABLED
  • +
  • UART: IO=128
  • +
  • UART: IO=136
  • +
  • UART: IO=160
  • +
  • UART: IO=168
  • +
  • SIO MODE=RC, IO=128, CHANNEL A, INTERRUPTS ENABLED
  • +
  • SIO MODE=RC, IO=128, CHANNEL B, INTERRUPTS ENABLED
  • +
  • SIO MODE=RC, IO=132, CHANNEL A, INTERRUPTS ENABLED
  • +
  • SIO MODE=RC, IO=132, CHANNEL B, INTERRUPTS ENABLED
  • +
  • CH: IO=62
  • +
  • CH: IO=60
  • +
  • CHUSB: IO=62
  • +
  • CHUSB: IO=60
  • +
  • MD: TYPE=RAM
  • +
  • MD: TYPE=ROM
  • +
  • FD: MODE=RCWDC, IO=80, DRIVE 0, TYPE=3.5” HD
  • +
  • FD: MODE=RCWDC, IO=80, DRIVE 1, TYPE=3.5” HD
  • +
  • IDE: MODE=RC, IO=144, MASTER
  • +
  • IDE: MODE=RC, IO=144, SLAVE
  • +
  • PPIDE: IO=32, MASTER
  • +
  • PPIDE: IO=32, SLAVE
  • +
  • SD: MODE=SC, IO=12, UNITS=1
  • +
+

SC503 Z180 CPU Module

+

SC503 is a Z180 Processor card designed for Z50Bus.

+ +

ROM Image File: SCZ180_sc503_std.rom

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BusZ50
Default CPU Speed18.432 MHz
InterruptsMode 2
System TimerZ180
Serial Default115200 Baud
Memory ManagerZ180
ROM Size512 KB
RAM Size512 KB
+

Supported Hardware

+
    +
  • FP: LEDIO=160, SWIO=160
  • +
  • DSRTC: MODE=STD, IO=12
  • +
  • INTRTC: ENABLED
  • +
  • ASCI: IO=192, INTERRUPTS ENABLED
  • +
  • ASCI: IO=193, INTERRUPTS ENABLED
  • +
  • UART: IO=128
  • +
  • UART: IO=136
  • +
  • UART: IO=160
  • +
  • UART: IO=168
  • +
  • SIO MODE=RC, IO=128, CHANNEL A, INTERRUPTS ENABLED
  • +
  • SIO MODE=RC, IO=128, CHANNEL B, INTERRUPTS ENABLED
  • +
  • SIO MODE=RC, IO=132, CHANNEL A, INTERRUPTS ENABLED
  • +
  • SIO MODE=RC, IO=132, CHANNEL B, INTERRUPTS ENABLED
  • +
  • CH: IO=62
  • +
  • CH: IO=60
  • +
  • CHUSB: IO=62
  • +
  • CHUSB: IO=60
  • +
  • MD: TYPE=RAM
  • +
  • MD: TYPE=ROM
  • +
  • FD: MODE=RCWDC, IO=80, DRIVE 0, TYPE=3.5” HD
  • +
  • FD: MODE=RCWDC, IO=80, DRIVE 1, TYPE=3.5” HD
  • +
  • IDE: MODE=RC, IO=144, MASTER
  • +
  • IDE: MODE=RC, IO=144, SLAVE
  • +
  • PPIDE: IO=32, MASTER
  • +
  • PPIDE: IO=32, SLAVE
  • +
  • SD: MODE=SC, IO=12, UNITS=1
  • +
+

SC700 Z180 CPU Module

+

This configuration is specifically for systems based on the Z180 CPU +(eg. SC722) with 1MB linear memory (eg. SC721)

+ +

ROM Image File: SCZ180_sc700_std.rom

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BusRCBus
Default CPU Speed18.432 MHz
InterruptsMode 2
System TimerZ180
Serial Default115200 Baud
Memory ManagerZ180
ROM Size512 KB
RAM Size512 KB
+

Supported Hardware

+
    +
  • FP: LEDIO=0
  • +
  • LCD: IO=170, SIZE=20X4
  • +
  • DSRTC: MODE=STD, IO=12
  • +
  • INTRTC: ENABLED
  • +
  • ASCI: IO=192, INTERRUPTS ENABLED
  • +
  • ASCI: IO=193, INTERRUPTS ENABLED
  • +
  • UART: IO=128
  • +
  • UART: IO=136
  • +
  • UART: IO=160
  • +
  • UART: IO=168
  • +
  • SIO MODE=RC, IO=128, CHANNEL A, INTERRUPTS ENABLED
  • +
  • SIO MODE=RC, IO=128, CHANNEL B, INTERRUPTS ENABLED
  • +
  • SIO MODE=RC, IO=132, CHANNEL A, INTERRUPTS ENABLED
  • +
  • SIO MODE=RC, IO=132, CHANNEL B, INTERRUPTS ENABLED
  • +
  • CH: IO=62
  • +
  • CH: IO=60
  • +
  • CHUSB: IO=62
  • +
  • CHUSB: IO=60
  • +
  • MD: TYPE=RAM
  • +
  • MD: TYPE=ROM
  • +
  • FD: MODE=RCWDC, IO=80, DRIVE 0, TYPE=3.5” HD
  • +
  • FD: MODE=RCWDC, IO=80, DRIVE 1, TYPE=3.5” HD
  • +
  • IDE: MODE=RC, IO=16, MASTER
  • +
  • IDE: MODE=RC, IO=16, SLAVE
  • +
  • PPIDE: IO=32, MASTER
  • +
  • PPIDE: IO=32, SLAVE
  • +
  • SD: MODE=SC, IO=12, UNITS=1
  • +
+

`{=latex}

+

Z80-Retro SBC

+

The system comprises a Z80 retro computer board, and optonal VGA text +video card, and PIO Keyboard and Sound Card. The system uses a custom 60 +pin bus on a standard header.

+

(Not to be confused with a similar named project by John Winans +presented by John’s Basement on youTube)

+ +

ROM Image File: Z80RETRO_std.rom

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Bus60 pin
Default CPU Speed14.745 MHz
InterruptsMode 2
System TimerNone
Serial Default38400 Baud
Memory ManagerZ2
ROM Size512 KB
RAM Size512 KB
+

Supported Hardware

+
    +
  • SIO MODE=Z80R, IO=128, CHANNEL A, INTERRUPTS ENABLED
  • +
  • SIO MODE=Z80R, IO=128, CHANNEL B, INTERRUPTS ENABLED
  • +
  • MD: TYPE=RAM
  • +
  • MD: TYPE=ROM
  • +
  • SD: MODE=Z80R, IO=104, UNITS=1
  • +
+

Zeta Z80 SBC

+

Zeta SBC is an Zilog Z80 based single board computer. It is inspired by +Ampro Little Board Z80 and N8VEM project. Zeta SBC is software +compatible with N8VEM SBC and Disk I/O boards.

+
    +
  • Creator: Sergey Kiselev
  • +
  • Retrobrew Wiki: Zeta + SBC
  • +
+

ROM Image File: ZETA_std.rom

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Bus-
Default CPU Speed8.000 MHz
InterruptsNone
System TimerNone
Serial Default38400 Baud
Memory ManagerSBC
ROM Size512 KB
RAM Size512 KB
+

Supported Hardware

+
    +
  • DSRTC: MODE=STD, IO=112
  • +
  • UART: IO=104
  • +
  • PPP: IO=96
  • +
  • PPPCON: ENABLED
  • +
  • PPPSD: ENABLED
  • +
  • MD: TYPE=RAM
  • +
  • MD: TYPE=ROM
  • +
  • FD: MODE=DIO, IO=54, DRIVE 0, TYPE=3.5” HD
  • +
+

Notes:

+
    +
  • If ParPortProp is installed, initial console output is determined by + JP1:
  • +
  • Shorted: console to on-board serial port
  • +
  • Open: console to ParPortProp video and keyboard
  • +
+

Zeta V2 Z80 SBC

+

Zeta SBC V2 is a redesigned version of Zeta SBC.

+

Compared to the first version this version features updated MMU with +four banks, each one of those banks can be mapped to any 16 KiB page in +1 MiB on-board memory. It adds Z80 CTC which is used for generating +periodic interrupts and as a vectored interrupt controller for UART and +PPI. The FDC is replaced with 37C65. Compared to FDC9266 used in Zeta +SBC it integrates input/output buffers and floppy disk control latch. +Additionally 37C65 FDC is easier to obtain than FDC9266. And lastly it +is made using CMOS technology and more power efficient than FDC9266

+ +

ROM Image File: ZETA2_std.rom

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Bus-
Default CPU Speed8.000 MHz
InterruptsMode 2
System TimerCTC
Serial Default38400 Baud
Memory ManagerZ2
ROM Size512 KB
RAM Size512 KB
+

Supported Hardware

+
    +
  • DSRTC: MODE=STD, IO=112
  • +
  • UART: IO=104
  • +
  • PPP: IO=96
  • +
  • PPPCON: ENABLED
  • +
  • PPPSD: ENABLED
  • +
  • MD: TYPE=RAM
  • +
  • MD: TYPE=ROM
  • +
  • FD: MODE=ZETA2, IO=48, DRIVE 0, TYPE=3.5” HD
  • +
  • CTC: IO=32, TIMER MODE=COUNTER, DIVISOR=18432, HI=256, LO=72, + INTERRUPTS ENABLED
  • +
+

Notes:

+
    +
  • If ParPortProp is installed, initial console output is determined by + JP1:
  • +
  • Shorted: console to on-board serial port
  • +
  • Open: console to ParPortProp video and keyboard
  • +
+

Device Drivers

+

This section briefly describes each of the possible devices that may be +discovered by RomWBW in your system.

+

Character

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
IDDescription
ACIAMC68B50 Asynchronous Communications Interface Adapter
ASCIZilog Z180 CPU Built-in Serial Ports
DUARTSCC2681 or compatible Dual UART
ESPCONESP32 Firmware-based Video Console
ESPSERESP32 Firmware-based Serial Interface
EZ80UARTeZ80 Serial Interface
LPTParallel I/O Controller
PIOZilog Parallel Interface Controller
PPPCONParPortProp Serial Console Interface
PRPCONPropIO Serial Console Interface
SCONS100 Console
SIOZilog Serial Port Interface
SSERSimple Serial Interface
UART16C550 Family Serial Interface
USB-FIFOFT232H-based ECB USB FIFO
Z2UZilog Z280 CPU Built-in Serial Ports
+

By default, RomWBW will use the first available character device it +discovers for the initial console. The following character devices are +scanned in the order shown. The available character devices depend on +the active platform and configuration.

+
    +
  1. SSER: Simple Serial Interface
  2. +
  3. ASCI: Zilog Z180 CPU Built-in Serial Ports
  4. +
  5. Z2U: Zilog Z280 CPU Built-in Serial Ports
  6. +
  7. UART: 16C550 Family Serial Interface
  8. +
  9. DUART: SCC2681 or compatible Dual UART
  10. +
  11. SIO: Zilog Serial Port Interface
  12. +
  13. EZ80UART: eZ80 Serial Port Interface
  14. +
  15. ACIA: MC68B50 Asynchronous Communications Interface Adapter
  16. +
  17. USB-FIFO: FT232H-based ECB USB FIFO
  18. +
+

Disk

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
IDDescription
CHSDCH37x SD Card Interface
CHUSBCH37x USB Drive Interface
FDIntel 8272 or compatible Floppy Disk Controller
HDSKSIMH Simulator Hard Disk
IDEIDE/ATA/ATAPI Hard Disk Interface
IMMZip Drive on PPI (IMM variant)
MDROM/RAM Disk
PPAZip Drive on PPI (PPA variant)
PPIDE8255 IDE/ATA/ATAPI Hard Disk Interface
PPPSDParPortProp SD Card Interface
PRPSDPropIO SD Card Interface
RFRAM Floppy Disk Interface
SDSD Card Interface
SYQIomega SparQ Drive on PPI
+

Video

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
IDDescription
CVDUMC8563-based Video Display Controller
EFEF9345 Video Display Controller
FVS100 FPGA Z80 Onboard VGA/Keyboard
GDCuPD7220 Video Display Controller
TMSTMS9918/38/58 Video Display Controller
VDUMC6845 Family Video Display Controller (*)
VGAHD6445CP4-based Video Display Controller
VRCVGARC Video Display Controller
+

Note:

+
    +
  • Reading bytes from the video memory of the VDU board (not Color VDU) + appears to be problematic. This is only an issue when the driver needs + to scroll a portion of the screen which is done by applications such + as WordStar or ZDE. You are likely to see screen corruption in this + case.
  • +
+

Keyboard

+ + + + + + + + + + + + + + + + + + + + + + + + + +
IDDescription
KBD8242 PS/2 Keyboard Controller
MSXKYBMSX Compliant Matrix Keyboard
NABUKBNABU Keyboard
PPKMatrix Keyboard
+

Audio

+ + + + + + + + + + + + + + + + + + + + + + + + + +
IDDescription
AYAY-3-8910/YM2149 Programmable Sound Generator
SN76489SN76489 Programmable Sound Generator
SPKBit-bang Speaker
YMYM2612 Programmable Sound Generator
+

RTC (RealTime Clock)

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
IDDescription
BQRTCBQ4845P Real Time Clock
DS5RTCMaxim DS1305 SPI Real-Time Clock w/ NVRAM
DS7RTCMaxim DS1307 PCF I2C Real-Time Clock w/ NVRAM
DS1501RTCMaxim DS1501/DS1511 Watchdog Real-Time Clock
DSRTCMaxim DS1302 Real-Time Clock w/ NVRAM
EZ80RTCeZ80 Real-Time Clock
INTRTCInterrupt-based Real Time Clock
PCFPCF8584-based I2C Real-Time Clock
RP5C01Ricoh RPC01A Real-Time Clock w/ NVRAM
SIMRTCSIMH Simulator Real-Time Clock
+

DsKy (DiSplay KeYpad)

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
IDDescription
FPSimple LED & Switch Front Panel
GM7303Prolog 7303 derived Display/Keypad
H8PHeath H8 Display/Keypad
ICMICM7218-based Display/Keypad on PPI
LCDHitachi HD44780-based LCD Display
PKDP8279-based Display/Keypad on PPI
+

System

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
IDDescription
CHCH375/376 USB Interface Controller
CTCZilog Clock/Timer
DMAZilog DMA Controller
ESPESP32 Firmware-based interface
EZ80TIMEReZ80 System Timer
KIOZilog Serial/ Parallel Counter/Timer (Z84C90)
PPPParPortProp Host Interface Controller
PRPPropIO Host Interface Controller
+

UNA Hardware BIOS

+

John Coffman has produced a new generation of hardware BIOS called UNA. +The standard RomWBW distribution includes its own hardware BIOS. +However, RomWBW can alternatively be constructed with UNA as the +hardware BIOS portion of the ROM. If you wish to use the UNA variant of +RomWBW, then just program your ROM with the ROM image called +“UNA_std.rom” in the Binary directory. This one image is suitable on +all of the platforms and hardware UNA supports.

+

UNA is customized dynamically using a ROM based setup routine and the +setup is persisted in the system NVRAM of the RTC chip. This means that +the single UNA-based ROM image can be used on most of the RetroBrew +platforms and is easily customized. UNA also supports FAT file system +access that can be used for in-situ ROM programming and loading system +images.

+

While John is likely to enhance UNA over time, there are currently a few +things that UNA does not support:

+
    +
  • Floppy Drives
  • +
  • Terminal Emulation
  • +
  • Zeta 1, N8, RCBus, Easy Z80, and Dyno Systems
  • +
  • Some older support boards
  • +
+

The UNA version embedded in RomWBW is the latest production release of +UNA. RomWBW will be updated with John’s upcoming UNA release with +support for VGA3 as soon as it reaches production status.

+

Please refer to the UNA BIOS Firmware +Page +for more information on UNA.

+

UNA Usage Notes

+
    +
  • At startup, UNA will display a prompt similar to this:
  • +
+

Boot UNA unit number or ROM? [R,X,0..3] (R):

+

You generally want to choose ‘R’ which will then launch the RomWBW + loader. Attempting to boot from a disk using a number at the UNA + prompt will only work for the legacy (hd512) disk format. However, if + you go to the RomWBW loader, you will be able to perform a disk boot + on either disk format.

+
    +
  • +

    The disk images created and distributed with RomWBW do not have the + correct system track code for UNA. In order to boot to disk under UNA, + you must first use SYSCOPY to update the system track of the target + disk. The UNA ROM disk has the correct system track files for UNA: + CPM.SYS and ZSYS.SYS. So, you can boot a ROM OS and then use one + of these files to update the system track.

    +
  • +
  • +

    The only operating systems supported at this time are CP/M 2 and + ZSDOS. NZ-COM is also supported because it uses the ZSDOS CBIOS. None + of the other RomWBW operating systems are supported such as CP/M 3, + ZPM3, and p-System.

    +
  • +
  • +

    Some of the RomWBW-specific applications are not UNA compatible.

    +
  • +
+
+
+ + + + + + + + + + + diff --git a/Introduction/index.html b/Introduction/index.html new file mode 100644 index 00000000..9b0ee826 --- /dev/null +++ b/Introduction/index.html @@ -0,0 +1,691 @@ + + + + + + + + + + + Introduction - RomWBW Documentation V3.6 + + + + + + + + + + + + + + + + +
+
+
+
+ +

RomWBW Introduction \ +Version 3.6 \ +Wayne Warthen (wwarthen@gmail.com) \ +30 May 2025

+

Overview

+

RomWBW software provides a complete, commercial quality implementation +of CP/M (and workalike) operating systems and applications for modern +Z80/180/280 retro-computing hardware systems.

+

A wide variety of platforms are supported including those produced by +these developer communities:

+ +

A complete list of the currently supported platforms is found in RomWBW +Hardware +.

+

Description

+

Primary Features

+

By design, RomWBW isolates all of the hardware specific functions in the +ROM chip itself. The ROM provides a hardware abstraction layer such that +all of the operating systems and applications on a disk will run on any +RomWBW-based system. To put it simply, you can take a disk (or CF/SD/USB +Card) and move it between systems transparently.

+

Supported hardware features of RomWBW include:

+
    +
  • Z80 Family CPUs including Z80, Z180, and Z280
  • +
  • Banked memory services for several banking designs
  • +
  • Disk drivers for RAM, ROM, Floppy, IDE ATA/ATAPI, CF, SD, USB, Zip, + Iomega
  • +
  • Serial drivers including UART (16550-like), ASCI, ACIA, SIO
  • +
  • Video drivers including TMS9918, SY6545, MOS8563, HD6445
  • +
  • Keyboard (PS/2) drivers via VT8242 or PPI interfaces
  • +
  • Real time clock drivers including DS1302, BQ4845
  • +
  • Support for CP/NET networking using Wiznet, MT011 or Serial
  • +
  • Built-in VT-100 terminal emulation support
  • +
+

A dynamic disk drive letter assignment mechanism allows mapping +operating system drive letters to any available disk media. +Additionally, mass storage devices (IDE Disk, CF Card, SD Card, etc.) +support the use of multiple slices (up to 256 per device). Each slice +contains a complete CP/M filesystem and can be mapped independently to +any drive letter. This overcomes the inherent size limitations in legacy +OSes and allows up to 2GB of addressable storage on a single device, +with up to 128MB accessible at any one time.

+

Included Software

+

Multiple disk images are provided in the distribution. Most disk images +contain a complete, bootable, ready-to-run implementation of a specific +operating system. A “combo” disk image contains multiple slices, each +with a full operating system implementation. If you use this disk image, +you can easily pick whichever operating system you want to boot without +changing media.

+

Some of the included software:

+
    +
  • Operating Systems (CP/M 2.2, ZSDOS, NZ-COM, CP/M 3, ZPM3, Z3PLUS, QPM + )
  • +
  • Support for other operating systems, p-System, FreeRTOS, and FUZIX.
  • +
  • Programming Tools (Z80ASM, Turbo Pascal, Forth, Cowgol)
  • +
  • C Compiler’s including Aztec-C, and HI-TECH C
  • +
  • Microsoft Basic Compiler, and Microsoft Fortran
  • +
  • Some games such as Colossal Cave, Zork, etc
  • +
  • Wordstar Word processing software
  • +
+

Some of the provided software can be launched directly from the ROM +firmware itself:

+
    +
  • System Monitor
  • +
  • Operating Systems (CP/M 2.2, ZSDOS)
  • +
  • ROM BASIC (Nascom BASIC and Tasty BASIC)
  • +
  • ROM Forth
  • +
+

A tool is provided that allows you to access a FAT-12/16/32 filesystem. +The FAT filesystem may be coresident on the same disk media as RomWBW +slices or on stand-alone media. This makes exchanging files with modern +OSes such as Windows, MacOS, and Linux very easy.

+

ROM Distribution

+

The RomWBW Repository +(https://github.com/wwarthen/RomWBW) on GitHub is the official +distribution location for all project source and documentation.

+

RomWBW is distributed as both source code and pre-built ROM and disk +images.

+

The pre-built ROM images distributed with RomWBW are based on the +default system configurations as determined by the hardware +provider/designer. The pre-built ROM firmware images are generally +suitable for most users.

+

The fully-built distribution releases are available on the RomWBW +Releases Page +(https://github.com/wwarthen/RomWBW/releases) of the repository.

+

On this page, you will normally see a Development Snapshot as well as +recent stable releases. Unless you have a specific reason, I suggest you +stick to the most recent stable release.

+

The asset named RomWBW-vX.X.X-Package.zip includes all pre-built ROM and +Disk images as well as full source code. The other assets contain only +source code and do not have the pre-built ROM or disk images.

+

Distribution Directory Layout

+

The RomWBW distribution is a compressed zip archive file organized in a +set of directories. Each of these directories has its own ReadMe.txt +file describing the contents in detail. In summary, these directories +are:

+ + + + + + + + + + + + + + + + + + + + + + + + + +
DirectoryDescription
BinaryThe final output files of the build process are placed here. Most importantly, the ROM images with the file names ending in “.rom” and disk images ending in .img.
DocContains various detailed documentation, both RomWBW specifically as well as the operating systems and applications.
SourceContains the source code files used to build the software and ROM images.
ToolsContains the programs that are used by the build process or that may be useful in setting up your system.
+

Building from Source

+

It is also very easy to modify and build custom ROM images that fully +tailor the firmware to your specific preferences. All tools required to +build custom ROM firmware under Windows are included – no need to +install assemblers, etc. The firmware can also be built using Linux or +MacOS after confirming a few standard tools have been installed.

+

Installation & Operation

+

In general, installation of RomWBW on your platform is very simple. You +just need to program your ROM with the correct ROM image from the RomWBW +distribution. Subsequently, you can write disk images on your disk +drives (IDE disk, CF Card, SD Card, etc.) which then provides even more +functionality.

+

Complete instructions for installation and operation of RomWBW are found +in the RomWBW User +Guide. +It is also a good idea to review the Release +Notes +for helpful release-specific information.

+

Documentation

+

There are several documents that form the core of the RomWBW +documentation:

+
    +
  • +

    RomWBW User + Guide + is the main user guide for RomWBW, it covers the major topics of how + to install, manage and use RomWBW, and includes additional guidance to + the use of some of the operating systems supported by RomWBW

    +
  • +
  • +

    RomWBW + Hardware + contains a description of all the hardware platforms, and devices + supported by RomWBW.

    +
  • +
  • +

    RomWBW + Applications + is a reference for the ROM-hosted and OS-hosted applications created + or customized to enhance the operation of RomWBW.

    +
  • +
  • +

    RomWBW Disk + Catalog + is a reference for the contents of the disk images provided with + RomWBW, with a description of many of the files on each image

    +
  • +
  • +

    RomWBW System + Guide + discusses much of the internal design and construction of RomWBW. It + includes a reference for the RomWBW HBIOS API functions.

    +
  • +
+

Each of the operating systems and ROM applications included with RomWBW +are sophisticated tools in their own right. It is not reasonable to +fully document their usage. However, you will find complete manuals in +PDF format in the Doc directory of the distribution. The intention of +this documentation is to describe the operation of RomWBW and the ways +in which it enhances the operation of the included applications and +operating systems.

+

Since RomWBW is purely a software product for many different platforms, +the documentation does not cover hardware construction, +configuration, or troubleshooting – please see your hardware provider +for this information.

+

Support

+

Getting Assistance

+

The best way to get assistance with RomWBW or any aspect of the +RetroBrew Computers projects is via one of the community forums:

+ +

Submission of issues and bugs are welcome at the RomWBW GitHub +Repository.

+

Also feel free to email Wayne Warthen at wwarthen@gmail.com. I am +happy to provide support adapting RomWBW to new or modified systems

+

Contributions

+

All source code and distributions are maintained on GitHub. +Contributions of all kinds to RomWBW are very welcome.

+

Acknowledgments

+

I want to acknowledge that a great deal of the code and inspiration for +RomWBW has been provided by or derived from the work of others in the +RetroBrew Computers Community. I sincerely appreciate all of their +contributions. The list below is probably missing many names – please +let me know if I missed you!

+
    +
  • +

    Andrew Lynch started it all when he created the N8VEM Z80 SBC which + became the first platform RomWBW supported. Some of his original code + can still be found in RomWBW.

    +
  • +
  • +

    Dan Werner wrote much of the code from which RomWBW was originally + derived and he has always been a great source of knowledge and advice.

    +
  • +
  • +

    Douglas Goodall contributed code, time, testing, and advice in “the + early days”. He created an entire suite of application programs to + enhance the use of RomWBW. Unfortunately, they have become unusable + due to internal changes within RomWBW. As of RomWBW 2.6, these + applications are no longer provided.

    +
  • +
  • +

    Sergey Kiselev created several hardware platforms for RomWBW including + the very popular Zeta.

    +
  • +
  • +

    David Giles created support for the Z180 CSIO which is now included SD + Card driver.

    +
  • +
  • +

    Phil Summers contributed the Forth and BASIC adaptations in ROM, the + AY-3-8910 sound driver, DMA support, and a long list of general code + and documentation enhancements.

    +
  • +
  • +

    Ed Brindley contributed some of the code that supports the RCBus + platform.

    +
  • +
  • +

    Spencer Owen created the RC2014 series of hobbyist kit computers which + has exponentially increased RomWBW usage. Some of his kits include + RomWBW.

    +
  • +
  • +

    Stephen Cousins has likewise created a series of hobbyist kit + computers at Small Computer Central and is distributing RomWBW with + many of them.

    +
  • +
  • +

    Alan Cox has contributed some driver code and has provided a great + deal of advice.

    +
  • +
  • +

    The CP/NET client files were developed by Douglas Miller.

    +
  • +
  • +

    Phillip Stevens contributed support for FreeRTOS.

    +
  • +
  • +

    Curt Mayer contributed the original Linux / MacOS build process.

    +
  • +
  • +

    UNA BIOS and FDISK80 are the products of John Coffman.

    +
  • +
  • +

    FLASH4 is a product of Will Sowerbutts.

    +
  • +
  • +

    CLRDIR is a product of Max Scane.

    +
  • +
  • +

    Tasty Basic is a product of Dimitri Theulings.

    +
  • +
  • +

    Dean Netherton contributed eZ80 CPU support, the sound driver + interface, and the SN76489 sound driver.

    +
  • +
  • +

    The RomWBW Disk Catalog document was produced by Mykl Orders.

    +
  • +
  • +

    Rob Prouse has created many of the supplemental disk images including + Aztec C, HiTech C, SLR Z80ASM, Turbo Pascal, Microsoft BASIC Compiler, + Microsoft Fortran Compiler, and a Games compendium.

    +
  • +
  • +

    Martin R has provided substantial help reviewing and improving the + User Guide and Applications documents.

    +
  • +
  • +

    Mark Pruden has made a wide variety of contributions including:

    +
  • +
  • +

    significant content in the Disk Catalog and User Guide

    +
  • +
  • creation of the Introduction and Hardware documents
  • +
  • Z3PLUS operating system disk image
  • +
  • COPYSL utility
  • +
  • SLABEL utility
  • +
  • a feature for RomWBW configuration by NVRAM
  • +
  • +

    the /B bulk mode of disk assignment to the ASSIGN utility

    +
  • +
  • +

    Jacques Pelletier has contributed the DS1501 RTC driver code.

    +
  • +
  • +

    Jose Collado has contributed enhancements to the TMS driver including + compatibility with standard TMS register configuration.

    +
  • +
  • +

    Kevin Boone has contributed a generic HBIOS date/time utility (WDATE).

    +
  • +
  • +

    Matt Carroll has contributed a fix to XM.COM that corrects the port + specification when doing a send.

    +
  • +
  • +

    Dean Jenkins enhanced the build process to accommodate the Raspberry + Pi 4.

    +
  • +
  • +

    Tom Plano has contributed a new utility (HTALK) to allow talking + directly to HBIOS COM ports.

    +
  • +
  • +

    Lars Nelson has contributed several generic utilities such as a + universal (OS agnostic) UNARC application.

    +
  • +
  • +

    Dylan Hall added support for specifying a secondary console.

    +
  • +
  • +

    Bill Shen has contributed boot loaders for several of his systems.

    +
  • +
  • +

    Laszlo Szolnoki has contributed an EF9345 video display controller + driver.

    +
  • +
  • +

    Ladislau Szilagyi has contributed an enhanced version of CP/M Cowgol + that leverages RomWBW memory banking.

    +
  • +
  • +

    Les Bird has contributed support for the NABU w/ Option Board

    +
  • +
+ +

Outside of the hardware platforms adapted to RomWBW, there are a variety +of projects that either target RomWBW specifically or provide a +RomWBW-specific variation. These efforts are greatly appreciated and are +listed below. Please contact the author if there are any other such +projects that are not listed.

+

Z88DK

+

Z88DK is a software powerful development kit for Z80 computers +supporting both C and assembly language. This kit now provides specific +library support for RomWBW HBIOS. The Z88DK project is hosted at +https://github.com/z88dk/z88dk.

+

Paleo Editor

+

Steve Garcia has created a Windows-hosted IDE that is tailored to +development of RomWBW. The project can be found at +https://github.com/alloidian/PaleoEditor.

+

Z80 fig-FORTH

+

Dimitri Theulings’ implementation of fig-FORTH for the Z80 has a +RomWBW-specific variant. The project is hosted at +https://github.com/dimitrit/figforth.

+

Assembly Language Programming for the RC2014 Zed

+

Bruce Hall has written a very nice document that describes how to +develop assembly language applications on RomWBW. It begins with the +setup and configuration of a new RC2014 Zed system running RomWBW. It +describes not only generic CP/M application development, but also RomWBW +HBIOS programming and bare metal programming. The latest copy of this +document is hosted at http://w8bh.net/Assembly for +RC2014Z.pdf.

+

Licensing

+

License Terms

+

RomWBW is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation, either version 3 of the License, or (at your +option) any later version.

+

RomWBW is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +more details.

+

You should have received a copy of the GNU General Public License along +with RomWBW. If not, see https://www.gnu.org/licenses/.

+

Portions of RomWBW were created by, contributed by, or derived from the +work of others. It is believed that these works are being used in +accordance with the intentions and/or licensing of their creators.

+

If anyone feels their work is being used outside of its intended +licensing, please notify:

+
+

Wayne Warthen
+wwarthen@gmail.com

+
+

RomWBW is an aggregate work. It is composed of many individual, +standalone programs that are distributed as a whole to function as a +cohesive system. Each program may have its own licensing which may be +different from other programs within the aggregate.

+

In some cases, a single program (e.g., CP/M Operating System) is +composed of multiple components with different licenses. It is believed +that in all such cases the licenses are compatible with GPL version 3.

+

RomWBW encourages code contributions from others. Contributors may +assert their own copyright in their contributions by annotating the +contributed source code appropriately. Contributors are further +encouraged to submit their contributions via the RomWBW source code +control system to ensure their contributions are clearly documented.

+

All contributions to RomWBW are subject to this license.

+
+
+ + + + + + + + + + + diff --git a/SystemGuide/Graphics/BankSwitchedMemory.svg b/SystemGuide/Graphics/BankSwitchedMemory.svg new file mode 100644 index 00000000..ef18a94e --- /dev/null +++ b/SystemGuide/Graphics/BankSwitchedMemory.svg @@ -0,0 +1,366 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Page-1 + + Data block.13 + + Sheet.14 + + + + Sheet.15 + + + + Sheet.16 + + + + + Data block.9 + + Sheet.10 + + + + Sheet.11 + + + + Sheet.12 + + + + + Data block + + Sheet.6 + + + + Sheet.7 + + + + Sheet.8 + + + + + Sheet.2 + $FE00 + + + $FE00 + + Sheet.3 + $D000 + + + $D000 + + Sheet.17 + $8000 + + + $8000 + + 3D stack middle + + Sheet.19 + + + + Sheet.20 + + + + + 3D stack middle.21 + + Sheet.22 + + + + Sheet.23 + + + + + 3D stack middle.24 + + Sheet.25 + + + + Sheet.26 + + + + + Sheet.27 + HBIOS Proxy (RST 08) + + HBIOS Proxy (RST 08) + + Sheet.28 + Application Area (TPA) + + Application Area (TPA) + + Sheet.29 + Operating System CP/M or ZSYS + + Operating System CP/M or ZSYS + + Sheet.30 + CBIOS + + CBIOS + + Sheet.31 + BDOS + + BDOS + + Sheet.32 + CCP + + CCP + + Data block.33 + + Sheet.34 + + + + Sheet.35 + + + + Sheet.36 + + + + + Sheet.37 + + + + Sheet.38 + HBIOS (Hardware Drivers) + + HBIOS (Hardware Drivers) + + Sheet.39 + + + + Sheet.40 + + + + Sheet.43 + Z80 CPU Address Space + + Z80 CPU Address Space + + Sheet.41 + Banked Lower 32K + + Banked Lower 32K + + Sheet.42 + Fixed Upper 32K + + Fixed Upper 32K + + Sheet.1 + $10000 + + + $10000 + + Sheet.4 + $0000 + + + $0000 + + Bracket + + + + Sheet.45 + Bank 0 + + Bank 0 + + Sheet.47 + App/OS Banks + + App/OS Banks + + Sheet.48 + Bank N-1 + + Bank N-1 + + Sheet.49 + Bank N + + Bank N + + Sheet.50 + • • • + + • • • + + Bracket.51 + + + + Sheet.55 + + + + Sheet.56 + Physical RAM (32K per bank) + + Physical RAM (32K per bank) + + Bracket.57 + ` + + + ` + + Sheet.58 + + + + 3D stack top + RAM Disk + + Sheet.61 + + + + Sheet.62 + + + + Sheet.63 + + + + RAM Disk + + + Pointer (1-D) + + + + Pointer (1-D).65 + + + + Pointer (1-D).66 + + + + Pointer (1-D).67 + + + + Sheet.70 + + + + Sheet.68 + HBIOS Function Call w/ Bank Switch + + HBIOS Function Call w/ Bank Switch + + Sheet.69 + RomWBW Bank Switched Memory Layout + + RomWBW Bank Switched Memory Layout + + Sheet.59 + + + + Sheet.52 + Fixed Mapping of Upper 32K to Last Bank + + Fixed Mapping of Upper 32K to Last Bank + + Sheet.72 + + + + Sheet.74 + + + + diff --git a/SystemGuide/Graphics/CharacterEmulationVideoServices.svg b/SystemGuide/Graphics/CharacterEmulationVideoServices.svg new file mode 100644 index 00000000..6632a956 --- /dev/null +++ b/SystemGuide/Graphics/CharacterEmulationVideoServices.svg @@ -0,0 +1,830 @@ + + + + + + + + + + + + + + + + Page-1 + + Sheet.81 + + + + Sheet.80 + + + + Sheet.1 + Character I/O Services + + Character I/O Services + + Sheet.2 + + + + Sheet.8 + + + + Sheet.9 + Emulation Services + + Emulation Services + + Sheet.10 + TTY + + TTY + + Sheet.11 + ANSI + + ANSI + + Sheet.12 + + + + Sheet.13 + + + + Sheet.14 + Video Display Adapter Services + + Video Display Adapter Services + + Sheet.18 + + + + Sheet.27 + UART + + UART + + Sheet.34 + ASCI + + ASCI + + Terminal.20 + + Sheet.36 + + + + Sheet.37 + + + + Sheet.38 + + + + Sheet.39 + + + + + Sheet.40 + CVDU + + CVDU + + Sheet.41 + + + + Sheet.47 + UPD7220 + + UPD7220 + + Sheet.54 + N8 + + N8 + + Sheet.56 + CIOXXX + + CIOXXX + + Sheet.57 + VDAXXX + + VDAXXX + + Sheet.58 + Operating System / Utilities + + Operating System / Utilities + + Sheet.59 + Others... + + Others... + + Sheet.60 + + + + Sheet.61 + + + + Sheet.62 + EMUXXX + + EMUXXX + + Sheet.15 + + + + Terminal.16 + + Sheet.42 + + + + Sheet.43 + + + + Sheet.44 + + + + Sheet.45 + + + + + Sheet.46 + + + + Terminal.48 + + Sheet.49 + + + + Sheet.50 + + + + Sheet.51 + + + + Sheet.52 + + + + + Sheet.53 + + + + Terminal.22 + + Sheet.23 + + + + Sheet.24 + + + + Sheet.25 + + + + Sheet.26 + + + + + Sheet.28 + + + + Terminal.29 + + Sheet.30 + + + + Sheet.31 + + + + Sheet.32 + + + + Sheet.33 + + + + + Sheet.35 + + + + Sheet.55 + RS-232 + + RS-232 + + Sheet.63 + RS-232 + + RS-232 + + Sheet.64 + VGA + + VGA + + Sheet.65 + VGA + + VGA + + Sheet.66 + NTSC + + NTSC + + Sheet.67 + UART + + UART + + Sheet.68 + ASCI + + ASCI + + Sheet.69 + VDU + + VDU + + Sheet.74 + SY6545 + + SY6545 + + Sheet.75 + MC8563 + + MC8563 + + Sheet.76 + uPD7220 + + uPD7220 + + Sheet.79 + Character / Emulation / Video Services + + Character / Emulation / Video Services + + Sheet.82 + HBIOS + + HBIOS + + Sheet.83 + HARDWARE + + HARDWARE + + Sheet.84 + TMS9918 + + TMS9918 + + Terminal.87 + + Sheet.88 + + + + Sheet.89 + + + + Sheet.90 + + + + Sheet.91 + + + + + Sheet.92 + VDU + + VDU + + Sheet.93 + + + + Sheet.94 + NTSC + + NTSC + + Sheet.96 + + + + Sheet.7 + + + + Sheet.17 + + + + Sheet.3 + + + + Sheet.4 + + + + diff --git a/SystemGuide/Graphics/Logo.svg b/SystemGuide/Graphics/Logo.svg new file mode 100644 index 00000000..586d6f1f --- /dev/null +++ b/SystemGuide/Graphics/Logo.svg @@ -0,0 +1,62 @@ + + + + + + + + Page-1 + + Sheet.34 + + + + Sheet.35 + + + + Sheet.36 + + + + Sheet.38 + + + + Sheet.39 + + + + Sheet.44 + + + + Sheet.48 + + + + Sheet.49 + + + + Sheet.50 + + + + Sheet.52 + + + + Sheet.53 + + + + diff --git a/SystemGuide/Graphics/Panel.svg b/SystemGuide/Graphics/Panel.svg new file mode 100644 index 00000000..ca83e5d7 --- /dev/null +++ b/SystemGuide/Graphics/Panel.svg @@ -0,0 +1,369 @@ + + + + + + + + Page-1 + + Sheet.1 + + + + Sheet.2 + + + + Sheet.3 + + + + Sheet.8 + + + + Sheet.9 + + + + Sheet.10 + + + + Sheet.11 + + + + Sheet.12 + + + + Sheet.13 + + + + Sheet.14 + + + + Sheet.18 + + + + Sheet.19 + + + + Sheet.20 + + + + Sheet.21 + + + + Sheet.22 + + + + Sheet.23 + + + + Sheet.24 + + + + Sheet.25 + + + + Sheet.26 + + + + Sheet.27 + + + + Sheet.28 + + + + Sheet.29 + + + + Sheet.30 + + + + Sheet.31 + + + + Sheet.32 + + + + Sheet.33 + + + + Sheet.34 + + + + Sheet.35 + 8 + + 8 + + Sheet.36 + 4 + + 4 + + Sheet.37 + 2 + + 2 + + Sheet.38 + 1 + + 1 + + Sheet.39 + High + + High + + Sheet.40 + + + + Sheet.41 + + + + Sheet.42 + + + + Sheet.43 + 8 + + 8 + + Sheet.44 + 4 + + 4 + + Sheet.45 + 2 + + 2 + + Sheet.46 + 1 + + 1 + + Sheet.47 + Low + + Low + + Sheet.48 + 7 + + 7 + + Sheet.49 + 6 + + 6 + + Sheet.50 + 5 + + 5 + + Sheet.52 + 4 + + 4 + + Sheet.53 + 3 + + 3 + + Sheet.54 + 2 + + 2 + + Sheet.55 + 1 + + 1 + + Sheet.56 + 0 + + 0 + + Sheet.57 + + + + Sheet.58 + Auto + + Auto + + Sheet.59 + Menu + + Menu + + Sheet.61 + + + + Sheet.62 + CRT + + CRT + + Sheet.63 + Serial + + Serial + + Sheet.64 + + + + Sheet.65 + Sec + + Sec + + Sheet.66 + Pri + + Pri + + Sheet.67 + + + + Sheet.68 + Disk + + Disk + + Sheet.69 + ROM + + ROM + + Sheet.70 + + + + Sheet.71 + Floppy + + Floppy + + Sheet.72 + Hard + + Hard + + Sheet.73 + + + + Sheet.74 + 4 + + 4 + + Sheet.75 + 2 + + 2 + + Sheet.76 + 1 + + 1 + + Sheet.78 + ROM App / Boot Slice + + ROM App / Boot Slice + + Sheet.79 + ROM Apps: 0=Monitor 1=BASIC 2=Forth 3=Game 4=CP/M 2.2 5=Z-Sys... + + ROM Apps: 0=Monitor 1=BASIC 2=Forth 3=Game 4=CP/M 2.2 5=Z-System 6=Net Boot 7=User + + Sheet.80 + + + + Sheet.81 + + + + Sheet.82 + + + + Sheet.84 + Console + + Console + + Sheet.85 + + + + Sheet.86 + + + + Sheet.87 + + + + Sheet.88 + Boot + + Boot + + diff --git a/SystemGuide/Graphics/hd1k.svg b/SystemGuide/Graphics/hd1k.svg new file mode 100644 index 00000000..2581bfe1 --- /dev/null +++ b/SystemGuide/Graphics/hd1k.svg @@ -0,0 +1,1088 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Page-1 + + + + Sheet.95 + 0 + + + + 0 + + Sheet.101 + 1 + + + + 1 + + Sheet.102 + 2 + + + + 2 + + Sheet.103 + 3 + + + + 3 + + Sheet.105 + . . . + + + + . . . + + Sheet.104 + N + + + + N + + Sheet.201 + + + + Sheet.69 + RomWBW Hard Disk Anatomy (Modern / hd1k) + + + + RomWBW Hard Disk Anatomy (Modern / hd1k) + + Sheet.106 + RomWBW Hard Disk (IDE/ATA/ATAPI/CF/SD/USB) + + + + RomWBW Hard Disk (IDE/ATA/ATAPI/CF/SD/USB) + + Sheet.107 + FAT Partition + + + + FAT Partition + + Sheet.119 + Sector 0 + + + + Sector 0 + + Sheet.120 + + + + Sheet.121 + + + + Sheet.122 + Type 2E + + + + Type 2E + + Sheet.123 + Type 06 + + + + Type 06 + + Sheet.124 + + + + Sheet.125 + + + + Sheet.126 + Partition Table + + + + Partition Table + + Sheet.131 + + + + Bracket.132 + + + + + + + Sheet.135 + + + + Sheet.139 + CP/M System Area (16 KB) + + + + CP/M System Area (16 KB) + + Sheet.141 + + + + Sheet.142 + + + + Sheet.143 + + + + Sheet.144 + + + + Sheet.165 + + + + Sheet.166 + + + + Sheet.167 + + + + Sheet.168 + + + + Stack pointer.179 + + + + + + + Sheet.202 + RomWBW Partition (8MB * N) + + + + RomWBW Partition (8MB * N) + + Sheet.205 + Prefix (1 MB typical) + + + + Prefix (1 MB typical) + + Dynamic connector + + + + Dynamic connector.207 + + + + Sheet.118 + MBR + + + + MBR + + Sheet.208 + + + + Sheet.128 + Slice (8 MB) + + + + Slice (8 MB) + + Bracket.146 + + + + + + + Sheet.581 + + + + Sheet.582 + CP/M File System (8,176 KB) + + + + CP/M File System (8,176 KB) + + Sheet.583 + + + + Sheet.590 + + + + Bracket.301 + + + + + + + Bracket.592 + + + + + + + diff --git a/SystemGuide/Graphics/hd512.svg b/SystemGuide/Graphics/hd512.svg new file mode 100644 index 00000000..c4cfa578 --- /dev/null +++ b/SystemGuide/Graphics/hd512.svg @@ -0,0 +1,236 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Page-1 + + Sheet.69 + RomWBW Hard Disk Anatomy (Classic / hd512) + + RomWBW Hard Disk Anatomy (Classic / hd512) + + Sheet.259 + 0 + + 0 + + Sheet.260 + 1 + + 1 + + Sheet.261 + 2 + + 2 + + Sheet.262 + 3 + + 3 + + Sheet.263 + . . . + + . . . + + Sheet.264 + N + + N + + Sheet.265 + + + + Sheet.266 + RomWBW Hard Disk (IDE/ATA/ATAPI/CF/SD/USB) + + RomWBW Hard Disk (IDE/ATA/ATAPI/CF/SD/USB) + + Sheet.267 + FAT Partition + + FAT Partition + + Sheet.268 + Sector 0 + + Sector 0 + + Sheet.269 + + + + Sheet.270 + + + + Sheet.271 + Type 06 + + Type 06 + + Sheet.272 + + + + Sheet.273 + + + + Sheet.274 + + + + Sheet.275 + Partition Table + + Partition Table + + Sheet.276 + + + + Bracket.132 + + + + Sheet.278 + + + + Sheet.279 + CP/M System Area (128 KB) + + CP/M System Area (128 KB) + + Sheet.280 + + + + Sheet.281 + + + + Sheet.282 + + + + Sheet.283 + + + + Sheet.284 + + + + Sheet.285 + + + + Sheet.286 + + + + Sheet.287 + + + + Stack pointer.179 + + + + Sheet.289 + RomWBW Data (8,320 KB * N) + + RomWBW Data (8,320 KB * N) + + Dynamic connector.207 + + + + Sheet.294 + MBR + + MBR + + Sheet.295 + + + + Sheet.296 + Slice (8,320 KB) + + Slice (8,320 KB) + + Sheet.298 + + + + Sheet.299 + CP/M File System (8 MB) + + CP/M File System (8 MB) + + Sheet.300 + + + + Bracket.301 + + + + Bracket.302 + + + + diff --git a/SystemGuide/index.html b/SystemGuide/index.html new file mode 100644 index 00000000..aabcb0ca --- /dev/null +++ b/SystemGuide/index.html @@ -0,0 +1,7362 @@ + + + + + + + + + + + System Guide - RomWBW Documentation V3.6 + + + + + + + + + + + + + + + + +
+
+
+
+ +

RomWBW System Guide \ +Version 3.6 \ +Wayne Warthen (wwarthen@gmail.com) \ +30 May 2025

+

Overview

+

The objective of RomWBW is to provide firmware, operating systems, and +applications targeting the Z80 family of CPUs. The firmware, in the form +of a ROM module, acts as the hardware interface layer with a +well-defined API (the HBIOS). The associated operating systems and +applications are adapted to the HBIOS API, not specific hardware.

+

The HBIOS is modular and configurable. New hardware interfaces can be +added in the form of straightforward driver modules. Within certain +constraints, new hardware platforms can be supported by simply adjusting +values in a build configuration file.

+

RomWBW is geared toward hardware being developed in modern +retro-computing hobbyist communities, not as replacement software for +legacy hardware. As a result, RomWBW requires at least 128KB of bank +switched RAM.

+

The CP/M family of operating systems has been adapted to run under +RomWBW including CP/M 2.2, Z-System, CP/M 3, and several other variants.

+

RomWBW firmware (ROM) includes:

+
    +
  • +

    System startup code (bootstrap) and bootloader

    +
  • +
  • +

    A basic system/debug monitor

    +
  • +
  • +

    HBIOS (Hardware BIOS) with support for most typical hardware + components used in Z80 family computers

    +
  • +
  • +

    Diagnostics and customizable debugging information.

    +
  • +
  • +

    ROM-hosted operating systems (both CP/M 2.2 and Z-System)

    +
  • +
  • +

    A ROM disk containing the standard OS applications and a RAM disk for + working storage.

    +
  • +
+

It is appropriate to note that much of the code and components that make +up a complete RomWBW package are derived from pre-existing work. Most +notably, the embedded operating systems are simply ROM-based copies of +generic CP/M or ZSDOS. Much of the hardware support code was originally +produced by other members of the RetroBrew Computers Community.

+

The remainder of this document focuses on RomWBW HBIOS which is the +fundamental basis of RomWBW.

+

Background

+

The Z80 CPU architecture has a limited, 64K address range. In general, +this address space must accommodate a running application, disk +operating system, and hardware support code.

+

Modern retro-computing Z80 CPU platforms provide a physical address +space that is much larger than the CPU address space (typically 512K or +1MB of physical RAM). This additional memory can be made available to +the CPU using a technique called bank switching. To achieve this, the +physical memory is divided up into chunks (banks) of 32K each. A +designated area of the CPU’s 64K address space is then reserved to “map” +any of the physical memory chunks. You can think of this as a window +that can be adjusted to view portions of the physical memory in 32K +blocks. In the case of RomWBW, the lower 32K of the CPU address space is +used for this purpose (the window). The upper 32K of CPU address space +is assigned a fixed 32K area of physical memory that never changes. The +lower 32K can be “mapped” on the fly to any of the 32K banks of physical +memory at a time. The primary constraint is that the CPU cannot be +executing code in the lower 32K of CPU address space at the time that a +bank switch is performed.

+

By utilizing the pages of physical RAM for specific purposes and +swapping in the correct page when needed, it is possible to utilize +substantially more than 64K of RAM. Because the retro-computing +community has now produced a very large variety of hardware, it has +become extremely important to implement a bank switched solution to +accommodate the maximum range of hardware devices and desired +functionality.

+

General Design Strategy

+

The design goal is to locate as much of the hardware dependent code as +possible out of normal 64KB CP/M address space and into a bank switched +area of memory. A very small code shim (proxy) is located in the top 512 +bytes of CPU memory. This proxy is responsible for redirecting all +hardware BIOS (HBIOS) calls by swapping the “driver code” bank of +physical RAM into the lower 32K and completing the request. The +operating system is unaware this has occurred. As control is returned to +the operating system, the lower 32KB of memory is switched back to the +original memory bank.

+

The HBIOS functions are invoked simply by placing function parameters in +Z80 registers and calling an address within the HBIOS proxy. +Additionally, HBIOS implements a complete hardware interrupt management +framework. When a hardware interrupt occurs, control vectors through the +HBIOS proxy which saves the machine state, selects the HBIOS driver bank +into memory, and transfers control to the registered driver’s interrupt +handler. Upon completion of interrupt processing, control returns via +the HBIOS proxy, machine state is restored, and normal processing +resumes. The interrupt management framework supports Z80 interrupt modes +1, 2, and 3 (Z280).

+

HBIOS is completely agnostic with respect to the operating system (it +does not know or care what operating system is using it). The operating +system makes simple calls to HBIOS to access any desired hardware +functions. Since the HBIOS proxy occupies only 512 bytes at the top of +memory, the vast majority of the CPU memory is available to the +operating system and the running application. As far as the operating +system is concerned, all of the hardware driver code has been magically +implemented inside of the small 512 byte area at the top of the CPU +address space.

+

Unlike some other Z80 bank switching schemes, there is no attempt to +build bank switching into the operating system itself. This is +intentional so as to ensure that any operating system can easily be +adapted without requiring invasive modifications to the operating system +itself. This also keeps the complexity of memory management completely +away from the operating system and applications.

+

There are some operating systems that have built-in support for bank +switching (e.g., CP/M 3). These operating systems are allowed to make +use of the bank switched memory and are compatible with HBIOS. However, +it is necessary that the customization of these operating systems take +into account the banks of memory used by HBIOS and not attempt to use +those specific banks.

+

Note that all code and data are located in RAM memory during normal +execution. While it is possible to use ROM memory to run code, it would +require that more upper memory be reserved for data storage. It is +simpler and more memory efficient to keep everything in RAM. At startup +(boot) all required code is copied to RAM (shadowed) for subsequent +execution.

+

Runtime Memory Layout

+

RomWBW divides the standard 64KB Z80 address space into 2 sections. The +lower 32KB is the “banked” area. This is the area that will contain any +of the 32KB chunks of physical RAM based on which bank is currently +selected. The upper 32KB is “fixed”. This area of memory is never +swapped out and is used to contain software and operating systems that +must remain in the Z80 address space.

+

Throughout this document, this mechanism of selecting banks of memory +into the lower 32K is referred to as memory management. Achieving this +functionality requires some type of hardware which is generally referred +to as the system’s Memory Management Unit (MMU). RomWBW supports a +variety of MMUs – but they all perform the same function of swapping +in/out banks of memory in the lower 32K of CPU address space.

+

Figure 4.1 depicts the memory layout for a system running the CP/M +operating system. Applications residing in TPA invoke BDOS services of +CP/M, BDOS invokes the custom CBIOS APIs, and finally CBIOS invokes +HBIOS functions as needed by calling into the HBIOS proxy. The HBIOS +proxy swaps in the HBIOS bank as needed to perform the requested +function.

+

Additional banks of RAM are used to create a virtual disk drive.

+
+ + +
+ +

Bank Id

+

RomWBW utilizes a specific assignment of memory banks for dedicated +purposes. A numeric Bank Id is used to refer to the memory banks. The +Bank Id is a single byte. In general, the Bank Id simply refers to each +of the 32K banks in sequential order. In other words, Bank Id 0 is the +first physical 32K, Bank Id 1 is the second, etc. However, the high +order bit of the Bank Id has a special meaning. If it is 0, it indicates +a ROM bank is being referred to. If it is 1, it indicates a RAM bank is +being referred to.

+

For example, let’s say we have a typical system with 512KB of ROM and +512KB of RAM. The following table demonstrates how Bank Ids represent +areas of physical memory.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Physical MemoryTypePhysical BankBank Id
0x000000-0x007FFFROM00x00
0x008000-0x00FFFFROM10x01
0x010000-0x07FFFFROM2-150x02-0x0F
0x080000-0x087FFFRAM160x80
0x088000-0x08FFFFRAM170x81
0x090000-0x0FFFFFRAM18-310x82-0x8F
+

Note that Bank Id 0x00 is always the first bank of ROM and 0x80 is +always the first bank of RAM. If there were more banks of physical +ROM, they would be assigned Bank Ids starting with 0x10. Likewise, +additional bank of physical RAM would be assigned Bank Ids starting with +0x90.

+

The Bank Id is used in all RomWBW API functions when referring to the +mapping of banks to the lower 32K bank area of the processor. In this +way, all RomWBW functions can refer to a generic Bank Id without needing +to understand how a specific hardware platform accesses the physical +memory areas. A single routine within the HBIOS is implemented for each +memory manager that maps Bank Ids to physical memory.

+

Bank Assignments

+

RomWBW requires dedicated banks of memory for specific purposes. It uses +Bank Ids via an algorithm to make these assignments. The following table +describes the way the banks are assigned. The Typical column shows the +specific values that would be assigned for a common system with 512KB of +ROM and 512KB of RAM (nROM=16, nRAM=16).

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Bank IdIdentityTypicalPurpose
0x00BID_BOOT0x00Boot Bank (HBIOS image)
0x01BID_IMG00x01Boot Loader, Monitor, ROM OSes, ROM Apps
0x02BID_IMG10x02ROM Apps
0x03BID_IMG20x03\<Reserved>
0x04BID_ROMD00x04First ROM Disk Bank
nROM - 10x0FLast ROM Disk Bank
0x80BID_BIOS0x80HBIOS (working copy)
0x81BID_RAMD00x81First RAM Disk Bank
0x80 + nRAM - 80x88Last RAM Disk Bank
0x80 + nRAM - 7BID_APP00x89First Application Bank
0x80 + nRAM - 50x8BLast Application Bank
0x80 + nRAM - 4BID_BUF0x8COS Disk Buffers
0x80 + nRAM - 3BID_AUX0x8DOS Code Bank
0x80 + nRAM - 2BID_USR0x8EUser Bank (CP/M TPA)
0x80 + nRAM - 1BID_COM0x8FCommon Bank
+

In this table, nROM and nRAM refer to the number of corresponding ROM +and RAM banks in the the system.

+

The contents of the banks referred to above are described in more detail +below:

+

Boot Bank:
+The Boot Bank receives control when a system is first powered on. It +contains a ROM (read-only) copy of the HBIOS. At boot, it does minimal +hardware initialization, then copies itself to the HBIOS bank in RAM, +then resumes execution from the RAM bank.

+

Boot Loader:
+The application that handles loading of ROM or Disk based applications +including operating systems. It copies itself to a RAM bank at the start +of it’s execution.

+

Monitor:
+The application that implements the basic system monitor functions. It +copies itself to a RAM bank at the start of it’s execution.

+

ROM OSes:
+Code images of CP/M 2.2 and Z-System which are copied to RAM and +executed when a ROM-based operating system is selected in the Boot +Loader.

+

ROM Applications:
+Various ROM-based application images such as BASIC, FORTH, etc. They can +be selected in the Boot Loader. The Boot Loader will copy the +application image to a RAM bank, then transfer control to it.

+

ROM Disk:
+A sequential series of banks assigned to provide the system ROM Disk +contents.

+

HBIOS:
+This bank hosts the running copy of the RomWBW HBIOS.

+

RAM Disk:
+A sequential series of banks assigned to provide the system RAM Disk.

+

Application Bank:
+A sequential series of banks that are available for use by applications +that wish to utilize banked memory.

+

OS Disk Buffers:
+This bank is used by CP/M 3 and ZPM3 for disk buffer storage.

+

OS Code Bank:
+This bank is used by CP/M 3 and ZPM3 as an alternate bank for code. This +allows these operating systems to make additional TPA space available +for applications.

+

User Bank:
+This is the default bank for applications to use. This includes the +traditional TPA space for CP/M.

+

Common Bank:
+This bank is mapped to the upper 32K of the processors memory space. It +is a fixed mapping that is never changed in normal RomWBW operation +hence the name “Common”.

+

Memory Managers

+

The following hardware memory managers are supported by RomWBW. The +operation of these memory managers is not documented here – please refer +to the documentation of your hardware provider for that.

+

Z2:
+Memory memory manager introduced by Sergey Kiselv in the Zeta 2 SBC. +Popular in many RCBus systems.

+

Z180:
+Memory manager built into the Z180 CPU

+

Z280:
+Memory manager built into the Z280 CPU

+

ZRC:
+Memory manager onboard the ZRC series of computers by Bill Shen.

+

SBC:
+Memory manager onboard the N8VEM SBC series of computers by Andrew +Lynch.

+

MBC:
+Memory manager onboard the Nhyodyne computer system by Andrew Lynch.

+

N8:
+Memory manager onboard the N8 SBC computer by Andrew Lynch.

+

EZ512:
+Memory manager onboard the EaZy80-512 Z80 CPU Module by Bill Shen.

+

RPH:
+Memory manager onboard the Rhyophyre computer system by Andrew Lynch.

+

The memory manager used is determined by the configuration choices that +are part of a RomWBW build process. A given ROM can only have a single +memory manager – it is not selected dynamically.

+

Disk Layout

+

Floppy Disk Layout

+

RomWBVW generally handles floppy disks in the same physical formats as +MS-DOS. However, the filesystem will normally be CP/M. The following +table lists the floppy disk formats used by RomWBW. In all cases, the +sector size is 512 bytes.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
HBIOS Media IDCapacityTracksHeadsSectors
MID_FD720720KB8029
MID_FD1441440KB80218
MID_FD360360KB4029
MID_FD1201200KB80215
MID_FD1111155KB77215
+

Hard Disk Layout

+

RomWBW supports the use of PC MBR hard disk partitioning (see +https://en.wikipedia.org/wiki/Disk_partitioning). When accessing a +hard disk device, HBIOS will look for a partition with type id 0x2E and +will use that partition exclusively for all storage. If a hard disk does +not have a valid partition table with a partition of type 0x2E, the +HBIOS will treat the hard disk as dedicated storage and will store data +starting at the first sector of the disk.

+

The use of a partition of type 0x2E is preferred for RomWBW and is +referred to as a “Modern” disk layout. If there is no RomWBW partition +on the disk, then the disk is designated as having a “Classic” disk +layout.

+

When a disk uses a RomWBW partition (type 0x2E) for storage (Modern +layout), the CP/M filesystems on that disk will utilize a format with +1,024 directory entries per filesystem. If there is no RomWBW partition, +the CP/M filesystems will have 512 directory entries per filesystem. As +a result, the Modern disk layout with a RomWBW partition is also +referred to as the “hd1k” layout indicating 1024 directory entries. +Similarly, the Classic disk layout (no partition of type 0x2E) is also +referred to as the “hd512” layout indicating 512 directory entries.

+

The layout type of any hard disk is simply dictated by the existence of +a RomWBW partition. This also means that if you add or remove a +partition table entry of type 0x2E on existing hard disk media, you will +lose access to any pre-existing CP/M data on the disk. If used, +partitioning should be done before putting any data on the disk.

+

WARNING: You can not mix the two hard disk layouts on one hard disk +device. You can use different layouts on different hard disk devices in +a single system though.

+

Regardless of whether a disk is Modern or Classic, RomWBW supports the +concept of CP/M filesystem slices. In general, CP/M filesystems are +limited to 8MB. Since current disk media is dramatically larger than +this, RomWBW implements a mechanism to put many (up to 256) CP/M +filesystems on a single disk. Each such filesystem is called a slice +referring to the idea that the disk has been sliced into many +independent CP/M filesystems. RomWBW allows the disk slices to be mapped +to the limited (16) drive letters of CP/M. The mapping can be modified +on-the-fly on a running system as desired.

+

If the case of a Modern disk layout (with a RomWBW partition), the +slices are contained within the defined partition area and the number of +slices is dictated by the size of the partition. In the case of a +Classic disk layout (no RomWBW partition), the slices are located at the +start of the disk (first sector). In either case, the slices are just +sequential areas of space on the hard disk.

+

RomWBW accesses all hard disks using Logical Block Addressing (pure +sector offset). When necessary, RomWBW simulates the following disk +geometry for operating systems:

+
    +
  • Sector = 512 Bytes
  • +
  • Track = 16 Sectors (8KB per Track)
  • +
  • Cylinder = 16 Tracks (256 Sectors per Cylinder, 128KB per Cylinder)
  • +
+

If one is used, the FAT Partition must not overlap the CP/M slices. The +FAT partition does not need to start immediately after the CP/M slices +nor does it need to extend to the end of the hard disk. Its location and +size are entirely determined by its corresponding partition table entry.

+

Drive letters in CP/M are ASSIGNed to the numbered slices as desired.
+At boot, RomWBW automatically assigns up to 8 slices to drive letters +starting with the first available drive letter (typically C:).

+

Microsoft Windows will assign a single drive letter to the FAT partition +when the CF/SD Card is inserted. The drive letter assigned has no +relationship to the CP/M drive letters assigned to CP/M slices.

+

In general, Windows, MacOS, or Linux know nothing about the CP/M slices +and CP/M knows nothing about the FAT partition. However, the FAT +application can be run under CP/M to access the FAT partition +programmatically.

+

Before being used, A CP/M slice must be (re)initialized using the CP/M +command CLRDIR. A CP/M slice can be made bootable by copying a system +image to the System Area using SYSCOPY.

+

The FAT partition can be created from CP/M using the FDISK80 +application. The FAT partition can be initialized using the FAT +application from CP/M using the command FAT FORMAT n: where n is the +RomWBW disk unit number containing the FAT partition to be formatted.

+

Modern Hard Disk Layout (hd1k)

+
+Modern Disk Layout + +
+ +

The CP/M filesystem on a Modern disk will accommodate 1,024 directory +entries.

+

The CP/M slices reside entirely within a hard disk partition of type +0x2E. The number of slices is determined by the number of slices that +fit within the partition spaces allocated up to the maximum of 256.

+

Classic Hard Disk Layout (hd512)

+
+Classic Disk Layout + +
+ +

The CP/M filesystem on a Classic disk will accommodate 512 directory +entries.

+

The CP/M slices reside on the hard disk starting at the first sector of +the hard disk. The number of CP/M slices is not explicitly recorded +anywhere on the hard disk. It is up to the system user to know how many +slices are being used based on the size of the hard disk media and/or +the start of a FAT partition.

+

A partition table may exist within the first sector of the first slice. +For Classic disks, the partition table defines only the location and +size of the FAT partition. The Partition Table does not control the +location or number of CP/M slices in any way.

+

The Partition Table resides in a sector that is shared with the System +Area of CP/M Slice 0. However, the RomWBW implementation of CP/M takes +steps to avoid changing or corrupting the Partition Table area.

+

The FAT partition can be created from CP/M using the FDISK80 +application. The user is responsible for ensuring that the start of the +FAT partition does not overlap with the area they intend to use for CP/M +slices. FDISK80 has a Reserve option to assist with this.

+

Mapping to Media ID

+

HBIOS has a definition of “Media ID”, which defines the type and +physical properties of disk media provided by an underlying storage +device. For a complete list of Media ID’s please see Disk Input/Output +(DIO).

+

There are two important Media ID’s relating to Hard Disk Layouts:

+ + + + + + + + + + + + + + + + + + + + +
MediaIDFormat / Meaning
MID_HD4Classic Disk Layout (hd512) –and– HBIOS Hard Disk Drive
MID_HDNEW10Modern Disk Layout (hd1k)
+

HBIOS typically does not understand the format of data on a device, +instead just treating all hard disks as raw sectors. MID_HD is the +typical Media ID used by HBIOS to describe high capacity hard disk media

+

When the Modern Disk Layout was added, the MID_HDNEW, was added to +differentiate (at the operating system level) between the Classic and +Modern layouts.

+

However HBIOS itself typically does NOT make this distinction, since the +use of these two formats is determined by the operating system based on +the partition table on the media. There are two important HBIOS +functions that deal with Media ID.

+ +

System Boot Process

+

A multi-phase boot strategy is employed. This is necessary because at +cold start, the CPU is executing code from ROM in lower memory which is +the same area that is bank switched.

+

RomWBW supports multiple boot techniques as described below. The most +common of these is the ROM boot.

+

ROM Boot

+

The ROM boot process normally begins with a system cold start (power on +or hardware reset). The hardware is responsible for ensuring that the +lower 32K of CPU memory (bank window) is mapped to the initial 32K of +the ROM. The Z80 CPU begins execution at address zero which will be +address zero of the ROM.

+

The following steps occur during the ROM boot process:

+
    +
  1. +

    The ROM code performs basic hardware initialization and ensures that + the top 32K of CPU memory is mapped to the proper RAM bank.

    +
  2. +
  3. +

    The ROM code installs the HBIOS proxy code into the top 512 bytes of + the CPU memory (0xFE00-0xFFFF).

    +
  4. +
  5. +

    Using the proxy code services, the full HBIOS code is copied from + the ROM bank to the RAM bank that it will use for normal processing.

    +
  6. +
  7. +

    Again using the proxy code services, the RAM copy of HBIOS is + activated in the bank window and execution transitions to the RAM + copy of HBIOS.

    +
  8. +
  9. +

    The HBIOS initializes the system console so that output can now be + displayed to the user.

    +
  10. +
  11. +

    The HBIOS now performs the full hardware discovery and + initialization process while displaying it’s progress.

    +
  12. +
  13. +

    The HBIOS displays a final summary of the hardware device unit + assignments and various configuration information.

    +
  14. +
  15. +

    The HBIOS loads the RomWBW Boot Loader from ROM into RAM and jumps + to it.

    +
  16. +
+

At this point, the user would normally use Boot Loader commands to +select and launch an operating system or applications from either ROM or +disk.

+

Note that the boot process is entirely operating system agnostic. It is +unaware of the operating system being loaded. The Boot Loader prompts +the user for the location of the binary image to load, but does not know +anything about what is being loaded (the image is usually an operating +system, but could be any executable code image). Once the Boot Loader +has loaded the image at the selected location, it will transfer control +to it. Assuming the typical situation where the image was an operating +system, the loaded operating system will then perform its own +initialization and begin normal operation.

+

Application Boot

+

Once the system is running (operating system loaded), it is possible to +reboot the system from a system image (file) contained on the OS file +system. This is referred to as an “Application Boot”. The process is +similar to a ROM boot, but the HBIOS code is loaded from an image file +instead of ROM. This boot technique is useful to: 1) test a new build of +a system image before programming it to the ROM; or 2) easily switch +between system images on the fly.

+

During the RomWBW build process, one of the output files produced is an +actual CP/M application (an executable .COM program file). Like the +normal .ROM files, this file is placed in the Binary directory with the +same name as the ROM file, but with the file extension of .ROM. Once you +have a running CP/M (or compatible) system, you can upload/copy this +application file to the filesystem. By executing this file, you will +initiate an Application Boot using the system image contained in the +application file itself.

+

Upon execution, the Application Boot program is loaded into memory by +the previously running operating system starting at \$0100. Note that +the program image contains a full copy of the HBIOS to be installed and +run. Once the Application Boot program is loaded by the previous +operating system, control is passed to it and it performs a system +initialization similar to the ROM Boot, but using the image loaded in +RAM. Once the new HBIOS completes its initialization, it will launch the +Boot Loader just like a ROM boot.

+

The Application Boot program actually contains two other components +beyond the new HBIOS. It has a copy of the Boot Loader and a copy of the +Z-System OS. This is done in case the new HBIOS requires updated +versions of the Boot Loader or OS to run. The Boot Loader is aware of +this boot mode and automatically adapts it’s menu appropriately.

+

If you restart your system, then it will revert to a ROM Boot from the +currently installed ROM.

+

RAM Boot

+

Some hardware supported by RomWBW has a special mechanism for loading +the boot and HBIOS code. These systems have no ROM chips. However, they +have a small hardware bootstrap that loads a chunk of code from a disk +device directly into RAM at system startup.

+

The startup then proceeds very much like the Application Boot process +described above. HBIOS is installed in its operating bank and control is +passed to the Boot Loader.

+

Boot Recovery

+

To assist users when driver faults or mis-configuration causes a boot +failure, RomWBW supports a limited recovery capability. This is achieved +by allowing the user to reboot their machine, loading a minimal driver +set. Implementation of this feature requires a hardware input “BOOT +RECOVERY” button to be available and appropriate software configuration +to be completed in the HBIOS.

+

When implemented, holding the “BOOT RECOVERY” button in after a reset or +power cycle will cause the normal driver load process to be skipped in +preference to a minimal set of drivers being loaded.

+

Typically this would be: Serial communication, RAM disk and parallel +port IDE interface drivers.

+

Platforms supporting this option currently are the MBC, Duodyne and +latter version of the SBC.

+

Configuration

+

RomWBW NVRAM Configuration

+

On systems with RTC devices (that have Non-Volatile RAM), RomWBW +supports storing some limited configuration option options inside this +RAM.

+

Several configuration options are currently supported; these are known +as Switches. The following switch ID’s are defined, and described in +sections below.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Switch NumberNameDescription
0x00-reserved-Reserved
0x01Boot OptionsROM or Disk Boot Settings
0x02-n/a--n/a- high order byte of previous switch
0x03Auto BootAutomatically boot enabled without user input
0x04 - 0xFE-future-Future general usage
0xFFStatus ResetGet Status or Reset Switches to Default
+

RomWBW uses bytes located at the start of RTC NVRAM, and includes a +Parity check of the bytes in NVRAM to check for authenticity before +using the configuration.

+ + + + + + + + + + + + + + + + + + + + + + + + + +
NVRAM ByteNameDescription
0x00Header ByteHeader Signature Byte ‘W’
0x01 - 0x03Switch DataActual Switch Data
0x04Parity CheckChecksum byte to check integrity
+

The above data is copied into the HBIOS Configuration Block (HCB) at +startup at the location starting at CB_SWITCHES.

+

Boot Options (NVSW_BOOTOPTS)

+

16 bit Switch defining the ROM application or Disk device to boot if +automatic booting is enabled.

+ + + + + + + + + + + + + + + + + + + + +
Bit 15Bits 14-8Bits 7-0
1 = ROM App-undefined-App to Boot (Char)
0 = DiskDisk Unit (0-127)Disk Slice (0-255)
+

Auto Boot (NVSW_AUTOBOOT)

+

8 bit Switch defining if the system should auto boot at startup.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Bits 7-6Bit 5Bit 4Bits 3-0
-unused-1 = Auto Boot Enabled-unused-0 = Immediate Boot with no delay
-unused-1 = Auto Boot Enabled-unused-(1-15) Timeout (seconds) before boot
-unused-0 = Auto Boot Disabled-unused--undefined-
+

Status Reset (0xFF)

+

The Status Reset switch is not a general purpose switch, it is a control +mechanism to allow the global status of all switches to be determined. +The meaning of the switch is different for Read (Get Status) and Write +(Reset NVRAM)

+

GET (Get Status)

+

The read Get Status of switches. This returns very specific values from +the function call.

+ + + + + + + + + + + + + + + + + + + + + + + + + +
StatusA RegisterZ / NZ Flag
NVRAM does not existA=0NZ flag set
NVRAM exists, but has not been initialisedA=1NZ flag set
NVRAM exists, and has been fully initialisedA=‘W’Z flag set
+

SET (Reset NVRAM)

+

Reset NVRAM to default values. This will wipe any existing data and set +default values into NVRAM.

+

Driver Model

+

The framework code for bank switching also allows hardware drivers to be +implemented mostly without concern for memory management. Drivers are +coded to simply implement the HBIOS functions appropriate for the type +of hardware being supported. When the driver code gets control, it has +already been mapped to the CPU address space and simply performs the +requested function based on parameters passed in registers. Upon return, +the bank switching framework takes care of restoring the original memory +layout expected by the operating system and application.

+

Drivers do need to be aware of the bank switching if a buffer address is +being used in the function call.

+
    +
  • +

    If the buffer address is in the lower 32K of RAM, then the memory it + points to will be from the User Bank, not the HBIOS bank which is now + active. In this case, the driver must use an inter-bank copy to access + the data.

    +
  • +
  • +

    If the buffer address is in the top 32K of RAM, then the driver will + have access to it directly even after a bank switch, so no special + steps are required.

    +
  • +
+

For some functions, the location of the buffer is required to be in the +top 32K of RAM to simplify the operation of the driver.

+

It is usually better if the OS or application calling a buffered +function places the buffer in the top 32K because this may avoid a +double-copy operation.

+

If driver code must make calls to other code, drivers, or utilities in +the HBIOS bank, it must make those calls directly (it must not use RST +08). This is to avoid a nested bank switch which is not supported at +this time.

+

Character / Emulation / Video Services

+

In addition to a generic set of routines to handle typical character +input/output, HBIOS also includes functionality for managing built-in +video display adapters. To start with there is a basic set of character +input/output functions, the CIOXXX functions, which allow for simple +character data streams. These functions fully encompass routing byte +stream data to/from serial ports. Note that there is a special character +pseudo-device called “CRT”. When characters are read/written to/from the +CRT character device, the data is actually passed to a built-in terminal +emulator which, in turn, utilizes a set of VDA (Video Display Adapter) +functions (such as cursor positioning, scrolling, etc.).

+

Figure 9.1 depicts the relationship between these components of HBIOS +video processing:

+
+Character / Emulation / Video Services + +
+ +

Normally, the operating system will simply utilize the CIOXXX functions +to send and receive character data. The Character I/O Services will +route I/O requests to the specified physical device which is most +frequently a serial port (such as UART or ASCI). As shown above, if the +CRT device is targeted by a CIOXXX function, it will actually be routed +to the Emulation Services which implement TTY, ANSI, etc. escape +sequences. The Emulation Services subsequently rely on the Video Display +Adapter Services as an additional layer of abstraction. This allows the +emulation code to be completely unaware of the actual physical device +(device independent). Video Display Adapter (VDA) Services contains +drivers as needed to handle the available physical video adapters.

+

Note that the Emulation and VDA Services API functions are available to +be called directly. Doing so must be done carefully so as to not corrupt +the “state” of the emulation logic.

+

Before invoking CIOXXX functions targeting the CRT device, it is +necessary that the underlying layers (Emulation and VDA) be properly +initialized. The Emulation Services must be initialized to specify the +desired emulation and specific physical VDA device to target. Likewise, +the VDA Services may need to be initialized to put the specific video +hardware into the proper mode, etc.

+

HBIOS Reference

+

Invocation

+

HBIOS functions are invoked by placing the required parameters in CPU +registers and executing an RST 08 instruction. Note that HBIOS does +not preserve register values that are unused. However, the values of the +Z80 alternate registers and IX/IY will be preserved (these registers may +be used within HBIOS, but will be saved and restored internally).

+

An alternate method of invoking HBIOS functions is to use CALL $FFF0. +Since the RST 08 vector exists in page zero of the CPU address space, +it may be paged out when alternate memory banks are selected. If this +may be true when you are invoking a function, you should use the CALL +method.

+

Normally, applications will not call HBIOS functions directly. It is +intended that the operating system makes all HBIOS function calls. +Applications that are considered system utilities may use HBIOS, but +must be careful not to modify the operating environment in any way that +the operating system does not expect.

+

In general, the desired function is placed in the B register. Register C +is frequently used to specify a sub-function or a target device unit +number. Additional registers are used as defined by the specific +function. Register A should be used to return function result +information. See below for result code definitions.

+

The character, disk, and video device functions all refer to target +devices using a logical device unit number that is passed in the C +register. Keep in mind that these unit numbers are assigned dynamically +at HBIOS initialization during the device discovery process. The +assigned unit numbers are displayed on the console at the conclusion of +device initialization. The unit assignments will never change after +HBIOS initialization. However, they can change at the next boot if there +have been hardware or BIOS customization changes. Code using HBIOS +functions should not assume fixed unit assignments.

+

Some functions utilize pointers to memory buffers. Unless otherwise +stated, such buffers can be located anywhere in the Z80 CPU 64K address +space. However, performance sensitive buffers (primarily disk I/O +buffers) will require double-buffering if the caller’s buffer is in the +lower 32K of CPU address space. For optimal performance, such buffers +should be placed in the upper 32K of CPU address space.

+

HBIOS also implements a small number of core functions in the HBIOS +proxy area at the top of RAM. These exist primarily to facilitate the +operation of normal HBIOS function calls. However, they are available to +be used by OSes and applications. These functions can only be invoked by +calling into a jump table in upper RAM.

+

Result Codes

+

The following function result codes are defined generically for all +HBIOS functions. Most function calls will return a result in register A.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CodeDefinition
0function succeeded
-1undefined error
-2function not implemented
-3invalid function
-4invalid unit number
-5out of memory
-6parameter out of range
-7media not present
-8hardware not present
-9I/O error
-10write request to read-only media
-11device timeout
-12invalid configuration
+

Character Input/Output (CIO)

+

Character Input/Output functions require that a Character Unit number be +specified in register C. This is the logical device unit number assigned +during the boot process that identifies all character devices uniquely. +A special value of 0x80 can be used for the Character Unit to refer to +the current console device.

+

All character units are assigned a Device Type ID which indicates the +specific hardware device driver that handles the unit. The table below +enumerates these values.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Device TypeIDDescriptionDriver
CIODEV_UART0x0016C550 Family Serial Interfaceuart.asm
CIODEV_ASCI0x01Z180 Built-in Serial Portsasci.asm
CIODEV_TERM0x02Terminalansi.asm
CIODEV_PRPCON0x03PropIO Serial Console Interfaceprp.asm
CIODEV_PPPCON0x04ParPortProp Serial Console Interfaceppp.asm
CIODEV_SIO0x05Zilog Serial Port Interfacesio.asm
CIODEV_ACIA0x06MC68B50 Asynchronous Interfaceacia.asm
CIODEV_PIO0x07Zilog Parallel Interface Controllerpio.asm
CIODEV_UF0x08FT232H-based ECB USB FIFOuf.asm
CIODEV_DUART0x09SCC2681 Family Dual UARTduart.asm
CIODEV_Z2U0x0AZilog Z280 Built-in Serial Portsz2u.asm
CIODEV_LPT0x0BParallel I/O Controllerlpt.asm
CIODEV_ESPCON0x0CESP32 VGA Consoleesp.asm
CIODEV_ESPSER0x0DESP32 Serial Portesp.asm
CIODEV_SCON0x0ES100 Consolescon.asm
CIODEV_SSER0x0FSimple Serial Consolesser.asm
CIODEV_EZ80UART0x10eZ80 Built-in UART0 Interfaceez80uart.asm
+

Character devices can usually be configured with line characteristics +such as speed, framing, etc. A word value (16 bit) is used to describe +the line characteristics as indicated below:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BitsCharacteristic
15-14Reserved (set to 0)
13RTS
12-8Baud Rate (see below)
7DTR
6XON/XOFF Flow Control
51 = Stick Parity(Mark/Space), 0 = Normal Parity (odd/even)
41 = Even/Space, 0 = Odd/Mark
3Parity Enable (set for true)
2Stop Bits (set for true)
1-0Data Bits (5-8 encoded as 0-3)
+

The 5-bit Baud Rate value (V) is encoded as V = 75 * 2^X * 3^Y. The +bits are defined as YXXXX.

+

Actual character values are a single byte (8 bits). The Character I/O +functions do not modify or interpret the values being sent/received so +they can be used to pass 8-bit binary data without corruption. Note that +some OSes will modify character data (truncate to 7 bits, etc.).

+

Function 0x00 – Character Input (CIOIN)

+ + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x00A: Status
C: Character UnitE: Character
+

Read and return a Character (E) from the specified Character Unit (C). +If no character(s) are available in the unit’s input buffer, this +function will wait indefinitely. The returned Status (A) is a standard +HBIOS result code.

+

Function 0x01 – Character Output (CIOOUT)

+ + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x01A: Status (0-OK, else error)
C: Character Unit
E: Character
+

Send a Character (E) via the specified Character Unit (C). If there is +no space available in the unit’s output buffer, the function will wait +indefinitely. The returned Status (A) is a standard HBIOS result code.

+

Function 0x02 – Character Input Status (CIOIST)

+ + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x02A: Status / Characters Pending
C: Character Unit
+

Return the count of Characters Pending (A) in the input buffer of the +specified Character Unit (C). If the unit has no input buffer or the +buffer utilization is not available, the function may return simply 0 or +1 where 0 means there is no character available and 1 means there is at +least one character available.

+

The value returned in register A is used as both a Status (A) code and +the return value. Negative values (bit 7 set) indicate a standard HBIOS +result (error) code. Otherwise, the return value represents the number +of characters in the input buffer.

+

Function 0x03 – Character Output Status (CIOOST)

+ + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x03A: Status / Space Free
C: Character Unit
+

Return the count of buffer Space Free (A) for the specified Character +Unit (C). For example, if a 16 byte output buffer contains 6 characters +waiting to be sent out the unit’s serial interface, this function would +return 10; the number of positions available in the output buffer. If +the port has no output buffer or the buffer utilization is not +available, the function may return simply 0 or 1 where 0 means there is +no buffer space available and 1 means there is space in the output +buffer for at least one character.

+

The return value in register A is used as both a status code and the +return value. Negative values (bit 7 set) indicate a standard HBIOS +result (error) code. Otherwise, the return value represents the buffer +space available.

+

Function 0x04 – Character I/O Initialization (CIOINIT)

+ + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x04A: Status
C: Character Unit
DE: Line Characteristics
+

Condition the interface of the specified Character Unit (C) according to +the specified Line Characteristics (DE). The definition of the line +characteristics value is described above. If DE contains -1 (0xFFFF), +then the device will be reinitialized with the previous line +characteristics used (a reset) and any buffer contents will be flushed. +The Status (A) is a standard HBIOS result code.

+

Not all line characteristics are supported by all character interfaces. +It is up to the driver of the character unit to decide how to deal with +characteristics that are not available. For example, many character +drivers do not allow flow control settings (RTS/CTS, XON/XOFF) to be +modified dynamically. In most cases, these settings are ignored by the +driver in this function call.

+

Function 0x05 – Character I/O Query (CIOQUERY)

+ + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x05A: Status
C: Character UnitDE: Line Characteristics
+

Returns the current Line Characteristics (DE) of the specified Character +Unit (C). The definition of the line characteristics value is described +above. The returned status (A) is a standard HBIOS result code.

+

Function 0x06 – Character I/O Device (CIODEVICE)

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x06A: Status
C: Character UnitC: Device Attributes
D: Device Type
E: Device Number
H: Device Mode
L: Device I/O Base Address
+

Returns device information for the specified Character Unit (C). The +status (A) is a standard HBIOS result code.

+

The two high bits of Device Attribute (C) are: 00 = RS/232, 01 = +Terminal, 10 = Parallel. The remaining bits should be ignored and are +used internally.

+

Device Type (D) indicates the specific hardware driver that handles the +specified Character Unit. Values are listed at the start of this +section. Device Number (E) indicates the physical device number assigned +per driver. For example, a Device Type of 0x50 with a Device Number of 2 +refers to the third port being handled by the SIO driver.

+

Device Mode (H) is used to indicate the variant of the chip or circuit +that is used by the specified unit. For example, for a UART, the value +indicates the chip variant. The Device I/O Base Address (L) indicates +the starting port address of the hardware interface that is servicing +the specified unit. Both of these values are considered driver specific. +Refer to the associated hardware driver for the values used.

+

Disk Input/Output (DIO)

+

Disk Input/Output functions require that a Disk Unit number be specified +in register C. This is the logical device unit number assigned during +the boot process that identifies all disk devices uniquely.

+

All character units are assigned a Device Type ID which indicates the +specific hardware device driver that handles the unit. The table below +enumerates their values.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Device TypeIDDescriptionDriver
DIODEV_MD0x00Memory Diskmd.asm
DIODEV_FD0x01Floppy Diskfd.asm
DIODEV_RF0x02RAM Floppyrf.asm
DIODEV_IDE0x03IDE Diskide.asm
DIODEV_ATAPI0x04ATAPI Disk (not implemented)
DIODEV_PPIDE0x05PPIDE Diskppide.asm
DIODEV_SD0x06SD Cardsd.asm
DIODEV_PRPSD0x07PropIO SD Cardprp.asm
DIODEV_PPPSD0x08ParPortProp SD Cardppp.asm
DIODEV_HDSK0x09SIMH HDSK Diskhdsk.asm
DIODEV_PPA0x0AIomega PPA Diskppa.asm
DIODEV_IMM0x0BIomega IMM Diskimm.asm
DIODEV_SYQ0x0CSyquest Sparq Disksyq.asm
DIODEV_CHUSB0x0DCH375/376 USB Diskch.asm
DIODEV_CHSD0x0ECH375/376 SD Cardch.asm
+

A fixed set of media types are defined. The currently defined media +types identifiers are listed below. Each driver will support one or more +of the defined media types.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MediaIDFormat
MID_NONE0No media installed
MID_MDROM1ROM Drive
MID_MDRAM2RAM Drive
MID_RF3RAM Floppy (LBA)
MID_HD4Hard Disk (LBA) w/ 512 directory entries
MID_FD72053.5” 720K Floppy
MID_FD14463.5” 1.44M Floppy
MID_FD36075.25” 360K Floppy
MID_FD12085.25” 1.2M Floppy
MID_FD11198” 1.11M Floppy
MID_HDNEW10Hard Disk (LBA) w/ 1024 directory entries
+

NOTE: HBIOS typically does not actually differentiate between MID_HD +and MID_HDNEW, it will generally only use MID_HD. See the section +Mapping to Media ID for information on this.

+

HBIOS supports both Cylinder/Head/Sector (CHS) and Logical Block +Addresses (CHS) when locating a sector for I/O (see DIOSEEK function). +For devices that are natively CHS (e.g., floppy disk), the HBIOS driver +can convert LBA values to CHS values according to the geometry of the +current media. For devices that are natively LBA (e.g., hard disk), the +HBIOS driver simulates CHS using a fictitious geometry provided by the +driver (typically 16 sectors per track and 16 heads per cylinder).

+

Function 0x10 – Disk Status (DIOSTATUS)

+ + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x10A: Status
C: Disk Unit
+

Returns the driver specific Status (A) of the specified disk device unit +(C) based on the last operation performed.

+

The return value in register A is used as both a device status and a +standard HBIOS result code. Negative values (bit 7 set) indicate a +standard HBIOS result (error) code. Otherwise, the return value +represents a driver-specific device status. In all cases, the value 0 +means OK.

+

Function 0x11 – Disk Reset (DIORESET)

+ + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x11A: Status
C: Disk Unit
+

This function performs a device dependent reset operation on the Disk +Unit specified (C). The driver will clear any error status on the disk +unit, attempt to reset the interface, and flag the disk unit for +initialization on the next I/O function call. Any prior media +identification will be cleared. The returned Status (A) is a standard +HBIOS result code.

+

If the specified disk unit (C) is one of multiple units on a single +hardware bus, then all units on that bus will be reset. For example, if +the master disk on an IDE bus is reset, then the slave disk will also be +reset.

+

Function 0x12 – Disk Seek (DIOSEEK)

+ + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x12A: Status
C: Disk Unit
DEHL: Sector Address
+

This function will set the desired sector to be used for the next I/O +operation on the specified Disk Unit (C). The returned Status (A) is a +standard HBIOS result code.

+

An actual seek operation is generally not performed on the disk hardware +by this function. The function typically just records the sector address +for subsequent I/O function calls.

+

The double-word Sector Address (DEHL) can represent either a Logical +Block Address (LBA) or a Cylinder/Head/Sector (CHS). Bit 7 of D is set +(1) for LBA mode and cleared (0) for CHS mode.

+

For LBA mode operation, the high bit is set and the rest of the +double-word is then treated as the logical sector address.

+

For CHS mode operation, the Sector Address (DEHL) registers are +interpreted as: D=Head, E=Sector, and HL=Track. All values (including +sector) are 0 relative.

+

Prior versions of the floppy driver did not accept LBA mode addresses. +However, this restriction has been removed as of HBIOS v3.1. At this +point, all disk drivers support both LBA and CHS addressing.

+

Function 0x13 – Disk Read (DIOREAD)

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x13A: Status
C: Disk UnitE: Sectors Read
D: Buffer Bank ID
E: Sector Count
HL: Buffer Address
+

Read Sector Count (E) sectors into the buffer located in Buffer Bank ID +(D) at Buffer Address (HL) starting at the Current Sector. The returned +Status (A) is a standard HBIOS result code.

+

The Current Sector is established by a prior DIOSEEK function call; +however, multiple read/write/verify function calls can be made after a +seek function. The Current Sector is incremented after each sector +successfully read. On error, the Current Sector will be the sector where +the error occurred. Sectors Read (E) indicates the number of sectors +successfully read.

+

The caller must ensure that the Buffer Address is large enough to +contain all sectors requested. Disk data transfers will be faster if the +buffer resides in the top 32K of memory because it avoids a double +buffer copy.

+

Also for buffers in the top 32K of memory the Bank ID is not strictly +required as this memory is alway mapped to the common bank. For buffers +in the bottom 32KB ram, the Bank ID is used to identify the bank to use +for the buffer. If you do not wih to use banked memory you will need to +provide the current Bank ID, which can be obtained using Function 0xF3 +– System Get Bank (SYSGETBNK)

+

Function 0x14 – Disk Write (DIOWRITE)

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x14A: Status
C: Disk UnitE: Sectors Written
D: Buffer Bank ID
E: Sector Count
HL: Buffer Address
+

Write Sector Count (E) sectors from the buffer located in Buffer Bank ID +(D) at Buffer Address (HL) starting at the Current Sector. The returned +Status (A) is a standard HBIOS result code.

+

The Current Sector is established by a prior DIOSEEK function call; +however, multiple read/write/verify function calls can be made after a +seek function. The Current Sector is incremented after each sector +successfully written. On error, the Current Sector will be the sector +where the error occurred. Sectors Written (E) indicates the number of +sectors successfully written.

+

Disk data transfers will be faster if the buffer resides in the top 32K +of memory because it avoids a double copy.

+

Function 0x15 – Disk Verify (DIOVERIFY)

+ + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x15A: Status
C: Disk UnitE: Sectors Verified
E: Sector Count
+

*** Function Not Implemented ***

+

Function 0x16 – Disk Format (DIOFORMAT)

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x16A: Status
C: Disk Unit
D: Head
E: Fill Byte
HL: Cylinder
+

*** Function Not Implemented ***

+

Function 0x17 – Disk Device (DIODEVICE)

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x17A: Status
C: Disk UnitC: Device Attributes
D: Device Type
E: Device Number
H: Device Unit Mode
L: Device I/O Base Address
+

Reports device information about the specified Disk Unit (C). The Status +(A) is a standard HBIOS result code.

+

The Device Attribute (C) value returned indicates various feature +indicators related to the device being referenced by the specified Disk +Unit (C). The high 3 bits apply to all devices. The definition of the +low 5 bits depends on whether the device is a Floppy (indicated by bit +5).

+

The common bits are:

+ + + + + + + + + + + + + + + + + + + + + +
BitsDefinition
7Floppy
6Removable
5High Capacity (>8 MB)
+

The Floppy specific bits are:

+ + + + + + + + + + + + + + + + + + + + + +
BitsDefinition
4-3Form Factor: 0=8”, 1=5.25”, 2=3.5”, 3=Other
2Sides: 0=SS, 1=DS
1-0Density: 0=SD, 1=DD, 2=HD, 3=ED
+

The non-Floppy specific bits are:

+ + + + + + + + + + + + + + + + + + + + + + + + + +
BitsDefinition
4LBA Capable
3-0Media Type: 0=Hard Disk, 1=CF, 2=SD, 3=USB,
4=ROM, 5=RAM, 6=FLASH, 7=RAMF, 8=CD-ROM,
9=Cartridge
+

Device Type (D) indicates the specific hardware driver that handles the +specified Disk Unit (C). Values are listed at the start of this section. +Device Number (E) indicates the physical device number assigned per +driver. For example, a Device Type of 0x30 with a Device Number of 1 +refers to the second disk being handled by the IDE driver.

+

Device Mode (H) is used to indicate the variant of the chip or circuit +that is used by the specified unit. For example, for an IDE unit, the +value indicates the IDE circuit variant. The Device I/O Base Address (L) +indicates the starting port address of the hardware interface that is +servicing the specified unit. Both of these values are considered driver +specific. Refer to the associated hardware driver for the values used.

+

Function 0x18 – Disk Media (DIOMEDIA)

+ + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x18A: Status
C: Disk UnitE: Media ID
E: Flags
+

Report the Media ID (E) for the for media in the specified Disk Unit +(C). If bit 0 of Flags (E) is set, then media discovery or verification +will be performed. The Status (A) is a standard HBIOS result code. If +there is no media in device, function will return an error status.

+

NOTE: This function will always return MID_HD for hard disk devices. +See the section Mapping to Media ID for +information on this. To determine if an HD1K formatted partition exists +on the hard disk please see the following function.

+

Function 0xE0 – Calculate Slice +(EXTSLICE)

+

Function 0x19 – Disk Define Media (DIODEFMED)

+ + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x19A: Status
C: Disk Unit
E: Media ID
+

*** Function Not Implemented ***

+

Function 0x1A – Disk Capacity (DIOCAPACITY)

+ + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x1AA: Status
C: Disk UnitDEHL: Sector Count
BC: Block Size
+

Report the current media capacity information for the specified Disk +Unit (C). The Sector Count (DEHL) is a double-word number representing +the total number of blocks on the device. Block Size (BC) contains the +block size in bytes. The Status (A) is a standard HBIOS result code. If +the media is unknown, an error will be returned.

+

This function will not attempt to discover or verify the media loaded in +the unit specified. You can use precede this function with the DIOMEDIA +function to force this if desired.

+

Function 0x1B – Disk Geometry (DIOGEOMETRY)

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x1BA: Status
C: Disk UnitD: Heads / LBA
E: Sectors
HL: Cylinder Count
BC: Block Size
+

Report the geometry for the media in the specified Disk Unit (C). If a +device uses LBA mode addressing natively, then the drivers simulated +geometry will be returned. The Status (A) is a standard HBIOS result +code. If the media is unknown, an error will be returned.

+

LBA capability is indicated by D:7. When set, the device is capable of +LBA addressing. Refer to Function 0x12 – Disk Seek +(DIOSEEK) for more information on +specifying LBA vs. CHS addresses.

+

Heads (D:6-0) refers to the number of heads per cylinder. Sectors (E) +refers to the number of sectors per track. Cylinder Count (HL) is the +total number of cylinders addressable for the media. Block Size (BC) is +the number of bytes in one sector.

+

Real Time Clock (RTC)

+

The Real Time Clock functions provide read/write access to the clock and +related Non-Volatile RAM.

+

HBIOS only supports a single RTC device since there is no reason to have +more than one at a time. The RTC unit is assigned a Device Type ID which +indicates the specific hardware device driver that handles the unit. The +table below enumerates these values.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Device TypeIDDescriptionDriver
RTCDEV_DS0x00Maxim DS1302 Real-Time Clock w/ NVRAMdsrtc.asm
RTCDEV_BQ0x01BQ4845P Real Time Clockbqrtc.asm
RTCDEV_SIMH0x02SIMH Simulator Real-Time Clocksimrtc.asm
RTCDEV_INT0x03Interrupt-based Real Time Clockintrtc.asm
RTCDEV_DS70x04Maxim DS1307 PCF I2C RTC w/ NVRAMds7rtc.asm
RTCDEV_RP50x05Ricoh RPC01A Real-Time Clock w/ NVRAMrp5rtc.asm
RTCDEV_EZ800x07eZ80 on-chip RTCez80rtc.asm
+

The time functions to get and set the time (RTCGTM and RTCSTM) require a +6 byte date/time buffer in the following format. Each byte is BCD +encoded.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OffsetContents
0Year (00-99)
1Month (01-12)
2Date (01-31)
3Hours (00-24)
4Minutes (00-59)
5Seconds (00-59)
+

Function 0x20 – RTC Get Time (RTCGETTIM)

+ + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x20A: Status
HL: Date/Time Buffer Address
+

Read the current value of the real-time clock and store the date/time in +the Date/Time Buffer pointed to by HL. The Status (A) is a standard +HBIOS result code.

+

Function 0x21 – RTC Set Time (RTCSETTIM)

+ + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x21A: Status
HL: Date/Time Buffer Address
+

Set the current value of the real-time clock based on the Date/Time +Buffer pointed to by HL. The Status (A) is a standard HBIOS result code.

+

Function 0x22 – RTC Get NVRAM Byte (RTCGETBYT)

+ + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x22A: Status
C: IndexE: Value
+

Read a single byte Value (E) from the Non-Volatile RAM of the RTC at the +byte offset Index (C). The Status (A) is a standard HBIOS result code.

+

Function 0x23 – RTC Set NVRAM Byte (RTCSETBYT)

+ + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x23A: Status
C: Index
E: Value
+

Set a single byte Value (E) of the Non-Volatile RAM of the RTC at the +byte offset Index (C). The Status (A) is a standard HBIOS result code.

+

Function 0x24 – RTC Get NVRAM Block (RTCGETBLK)

+ + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x24A: Status
HL: Buffer Address
+

Read the entire contents of the Non-Volatile RAM into to a buffer +pointed to by Buffer Address (HL). The Status (A) is a standard HBIOS +result code.

+

Function 0x25 – RTC Set NVRAM Block (RTCSETBLK)

+ + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x25A: Status
HL: Buffer Address
+

Write the entire contents of the Non-Volatile RAM from the buffer +pointed to by Buffer Address (HL). The Status (A) is a standard HBIOS +result code.

+

Function 0x26 – RTC Get Alarm (RTCGETALM)

+ + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x26A: Status
HL: Date/Time Buffer Address
+

Work in progress, documentation required…

+

Function 0x27 – RTC Set Alarm (RTCSETALM)

+ + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x27A: Status
HL: Date/Time Buffer Address
+

Work in progress, documentation required…

+

Function 0x28 – RTC DEVICE (RTCDEVICE)

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x28A: Status
C: Device Attributes
D: Device Type
E: Device Number
H: Device Unit Mode
L: Device I/O Base Address
+

Returns device information for the RTC unit. The Status (A) is a +standard HBIOS result code.

+

Device Attribute (C) values are not yet defined. Device Type (D) +indicates the specific hardware driver that handles the specified +character unit. Values are listed at the start of this section. Device +Number (E) indicates the physical device number assigned per driver +which is always 0 for RTC.

+

Device Mode (H) is used to indicate the variant of the chip or circuit +that is used by the specified unit. The Device I/O Base Address (L) +indicates the starting port address of the hardware interface that is +servicing the specified unit. Both of these values are considered driver +specific. Refer to the associated hardware driver for the values used.

+

Display Keypad (DSKY)

+

The Display Keypad functions provide access to a segment or LCD style +display and associated optional keypad

+

HBIOS only supports a single DSKY device since there is no reason to +have more than one at a time. If the system contains multiple DSKY +devices, only the first device discovered will be used. The DSKY unit is +assigned a Device Type ID which indicates the specific hardware device +driver that handles the unit. The table below enumerates these values.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Device TypeIDDescriptionDriver
DSKYDEV_ICM0x01Original ICM7218 based DSKYicm.asm
DSKYDEV_PKD0x02Next Gen Intel P8279 based DSKYpkd.asm
DSKYDEV_GM73030x03GM7303 LCD Display + Keypadgm7303.asm
DSKYDEV_LCD0x04HD44780-based LCD Displaylcd.asm
+

The keypad keys are identified by the following key ids. Not all keypads +will contain all keys.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Key IdKey DefinitionKey IdKey Definition
\$00Hex Numeric 0\$10Forward
\$01Hex Numeric 1\$11Backward
\$02Hex Numeric 2\$12Clear
\$03Hex Numeric 3\$13Enter
\$04Hex Numeric 4\$14Deposit
\$05Hex Numeric 5\$15Examine
\$06Hex Numeric 6\$16Go
\$07Hex Numeric 7\$17Boot
\$08Hex Numeric 8\$18F4
\$09Hex Numeric 9\$19F3
\$0AHex Numeric A\$1AF2
\$0BHex Numeric B\$1BF1
\$0CHex Numeric C
\$0DHex Numeric D
\$0EHex Numeric E
\$0FHex Numeric F
+

Function 0x30 – DSKY Reset (DSKYRESET)

+ + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x30A: Status
+

This function performs a device dependent reset operation on the DSKY. +The display will be cleared, keyboard queue will be flushed, and chip +will be reinitialized. The returned Status (A) is a standard HBIOS +result code.

+

Function 0x31 – DSKY (DSKYSTATUS)

+ + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x31A: Status / Characters Pending
+

Return the count of Characters Pending (A) in the input buffer of the +DSKY. If the unit has no input buffer or the buffer utilization is not +available, the function may return simply 0 or 1 where 0 means there is +no character available and 1 means there is at least one character +available.

+

The value returned in register A is used as both a Status (A) code and +the return value. Negative values (bit 7 set) indicate a standard HBIOS +result (error) code. Otherwise, the return value represents the number +of characters in the buffer.

+

Function 0x32 – DSKY Get Key (DSKYGETKEY)

+ + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x32A: Status
E: Character Value
+

Read and return a Character (E) from the DSKY. If no character(s) are +available in the unit’s input buffer, this function will wait +indefinitely. The returned Status (A) is a standard HBIOS result code.

+

The Character Value (E) returned is not ASCII. It is a keypad key id. +The possible id values are listed at the start of this section.

+

Function 0x33 – DSKY Show HEX (RTCSHOWHEX)

+ + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x33A: Status
DE:HL=Binary Value
+

Display the 32-bit binary value (DE:HL) in hex on the DSKY segment +display. All decimal points of the display will be off. The Status (A) +is a standard HBIOS result code.

+

Function 0x34 – DSKY Show Segments (DSKYSHOWSEG)

+ + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x34A: Status
HL: Buffer Address
+

Display the segment-encoded values on the segment display. The encoding +uses a small alphabet as defined below. The actual representation of a +character is determined by the driver. The entire display is updated and +it is assumed that an 8 character buffer will be pointed to by HL. The +buffer must reside in high memory. The Status (A) is a standard HBIOS +result code.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
0x00: ‘0’0x01: ‘1’0x02: ‘2’0x03: ‘3’
0x04: ‘4’0x05: ‘5’0x06: ‘6’0x07: ‘7’
0x08: ‘8’0x09: ‘9’0x0A: ‘A’0x0B: ‘B’
0x0C: ‘C’0x0D: ‘D’0x0E: ‘E’0x0F: ‘F’
0x10: ’ ’0x11: ‘-’0x12: ‘.’0x13: ‘p’
0x14: ‘o’0x15: ‘r’0x16: ‘t’0x17: ‘A’
0x18: ‘d’0x19: ‘r’0x1A: ‘G’
+

Function 0x35 – DSKY Keypad LEDs (DSKYKEYLEDS)

+ + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x35A: Status
HL: Buffer Address
+

Light the LEDs for the keypad keys according to the bitmap contained in +the buffer pointed to by HL. The buffer must be located in high memory +and is assumed to be 8 bytes.

+

At this time, the bitmap is specific to the PKD hardware and will be +ignored by all other hardware.

+

Function 0x36 – DSKY Status LED (DSKYSTATLED)

+ + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x36A: Status
D: LED Number
E: LED State
+

Set or clear the status LED specified in D. The state of the LED is +contained in E. If E=0, the LED will be turned off. If E=1, the LED will +be turned on.

+

This function is specific to the PKD hardware and will be ignored by all +other hardware. The Status (A) is a standard HBIOS result code.

+

Function 0x37 – DSKY Beep (DSKYBEEP)

+ + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x37A: Status
+

Beep the onboard speaker of the DSKY. This function is specific to the +PKD hardware. It will be ignored by the ICM hardware. The Status (A) is +a standard HBIOS result code.

+

Function 0x38 – DSKY Device (DSKYDEVICE)

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x38A: Status
C: Device Attributes
D: Device Type
E: Device Number
H: Device Unit Mode
L: Device I/O Base Address
+

Returns device information for the DSKY unit. The Status (A) is a +standard HBIOS result code.

+

Device Attribute (C) values are not yet defined. Device Type (D) +indicates the specific hardware driver that handles the specified +character unit. Values are listed at the start of this section. Device +Number (E) indicates the physical device number assigned per driver +which is always 0 for DSKY.

+

Device Mode (H) is used to indicate the variant of the chip or circuit +that is used by the specified unit. The Device I/O Base Address (L) +indicates the starting port address of the hardware interface that is +servicing the specified unit. Both of these values are considered driver +specific. Refer to the associated hardware driver for the values used.

+

Function 0x39 – DSKY Device (DSKYMESSAGE)

+ + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x39A: Status
C: Message ID
+

Instructs the display to show a textual representation of the associated +message on the display. The IDs are defined in std.asm.

+

Function 0x3A – DSKY Device (DSKYEVENT)

+ + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x3AA: Status
C: Event ID
+

Instructs the display to update itself in response to an internal HBIOS +state change. At this time the the events are:

+

0: CPU Speed Change
+1: Disk Activity

+

Video Display Adapter (VDA)

+

The VDA functions are provided as a common interface to Video Display +Adapters. Not all VDAs will include keyboard hardware. In this case, the +keyboard functions should return a failure status.

+

All video units are assigned a Device Type ID which indicates the +specific hardware device driver that handles the unit. The table below +enumerates their values.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Device TypeIDDescriptionDriver
VDADEV_VDU0x00MC6845 Family Video Display Controllervdu.asm
VDADEV_CVDU0x01MC8563-based Video Display Controllercvdu.asm
VDADEV_GDC0x02uPD7220 Video Display Controllergdc.asm
VDADEV_TMS0x03TMS9918/38/58 Video Display Controllertms.asm
VDADEV_VGA0x04HD6445CP4-based Video Display Controllervga.asm
VDADEV_VRC0x05VGARCvrc.asm
+

Depending on the capabilities of the hardware, the use of colors and +attributes may or may not be supported. If the hardware does not support +these capabilities, they will be ignored.

+

Color byte values are constructed using typical RGBI +(Red/Green/Blue/Intensity) bits. The high four bits of the value +determine the background color and the low four bits determine the +foreground color. This results in 16 unique color values for both +foreground and background. The following table illustrates the color +byte value construction:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 BitColor
Background7Intensity
 6Blue
 5Green
 4Red
Foreground3Intensity
 2Blue
 1Green
 0Red
+

The following table illustrates the resultant color for each of the +possible 16 values for foreground or background:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ForegroundBackgroundColor
n0 nnnn00000n 0000nnnnBlack
n1 nnnn00011n 0001nnnnRed
n2 nnnn00102n 0010nnnnGreen
n3 nnnn00113n 0011nnnnBrown
n4 nnnn01004n 0100nnnnBlue
n5 nnnn01015n 0101nnnnMagenta
n6 nnnn01106n 0110nnnnCyan
n7 nnnn01117n 0111nnnnWhite
n8 nnnn10008n 1000nnnnGray
n9 nnnn10019n 1001nnnnLight Red
nA nnnn1010An 1010nnnnLight Green
nB nnnn1011Bn 1011nnnnYellow
nC nnnn1100Cn 1100nnnnLight Blue
nD nnnn1101Dn 1101nnnnLight Magenta
nE nnnn1110En 1110nnnnLight Cyan
nF nnnn1111Fn 1111nnnnBright White
+

Attribute byte values are constructed using the following bit encoding:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BitEffect
7n/a (0)
6n/a (0)
5n/a (0)
4n/a (0)
3n/a (0)
2Reverse
1Underline
0Blink
+

The following codes are returned by a keyboard read to signify non-ASCII +keystrokes:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ValueKeystrokeValueKeystroke
0xE0F10xF0Insert
0xE1F20xF1Delete
0xE2F30xF2Home
0xE3F40xF3End
0xE4F50xF4PageUp
0xE5F60xF5PadeDown
0xE6F70xF6UpArrow
0xE7F80xF7DownArrow
0xE8F90xF8LeftArrow
0xE9F100xF9RightArrow
0xEAF110xFAPower
0xEBF120xFBSleep
0xECSysReq0xFCWake
0xEDPrintScreen0xFDBreak
0xEEPause0xFE
0xEFApp0xFF
+

Function 0x40 – Video Initialize (VDAINI)

+ + + + + + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x40A: Status
C: Video Unit
E: Video Mode
HL: Font Bitmap
+

Performs a full (re)initialization of the specified Video Unit (C). The +screen is cleared and the keyboard buffer is flushed. If the specified +Video Unit (C) supports multiple video modes, a Video Mode (E) can be +specified (set to 0 for default/not specified). Video Mode (E) values +are specific to each VDA. The returned Status (A) is a standard HBIOS +result code.

+

If the hardware and driver supports it, you can specify a Font Bitmap +(HL) buffer address containing the character bitmap data to be loaded +into the video processor. The buffer must be located entirely in the +top 32K of the CPU memory space. HL must be set to zero if no character +bitmap is specified (the driver will utilize a default character +bitmap).

+

Function 0x41 – Video Query (VDAQRY)

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x41A: Status
C: Video UnitC: Video Mode
HL: Font BitmapD: Rows
E: Columns
HL: Font Bitmap
+

Return information about the specified Video Unit (C). Video Mode (C) +will be set to the current video mode. Rows (D) and Columns (E) will +return the dimensions of the video display as measured in rows and +columns. Note that this is the count of rows and columns, not the +last row/column number. The returned Status (A) is a standard HBIOS +result code.

+

If the hardware and driver support it, you can specify a Font Bitmap +(HL) buffer address that will be filled with the current character +bitmap data. The buffer must be located entirely in the top 32K of +the CPU memory space. Font Bitmap (HL) must be set to zero if it +does not point to a proper buffer area or memory corruption will result.

+

If HL is not zero, it must point to a suitably sized memory buffer in +the upper 32K of CPU address space that will be filled with the current +character bitmap data. It is critical that HL be set to zero if it does +not point to a proper buffer area or memory corruption will result. If +the video device driver does not have the ability to provide character +bitmap data, then Font Bitmap (HL) will be set to zero on return.

+

Function 0x42 – Video Reset (VDARES)

+ + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x42A: Status
C: Video Unit
+

Performs a non-destructive reset of the specified Video Unit (C).
+Should re-initialize the video hardware without destroying the screen +contents or cursor position. The current video mode will not be changed. +The returned Status (A) is a standard HBIOS result code.

+

Function 0x43 – Video Device (VDADEV)

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x43A: Status
C: Video UnitC: Device Attributes
D: Device Type
E: Device Number
H: Device Unit Mode
L: Device I/O Base Address
+

Reports device information about the specified Video Unit (C). The +Status (A) is a standard HBIOS result code.

+

Device Attribute (C) values are not yet defined.

+

Device Type (D) indicates the specific hardware driver that handles the +specified Video Unit (C). Values are listed at the start of this +section. Device Number (E) indicates the physical device number assigned +per driver.

+

Device Mode (H) is used to indicate the variant of the chip or circuit +that is used by the specified unit. For example, for an TMS video unit, +the value indicates the TMS circuit variant. The Device I/O Base Address +(L) indicates the starting port address of the hardware interface that +is servicing the specified unit. Both of these values are considered +driver specific. Refer to the associated hardware driver for the values +used.

+

Function 0x44 – Video Set Cursor Style (VDASCS)

+ + + + + + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x44A: Status
C: Video Unit
D: Start/End
E: Style
+

If supported by the specified Video Unit (C), adjust the format of the +cursor such that the cursor starts at the pixel specified in the top +nibble of Start/End (D) and ends at the pixel specified in the bottom +nibble of Start/End (D). So, if D=0x08, a block cursor would be used +that starts at the top pixel of the character cell and ends at the ninth +pixel of the character cell. The Status (A) is a standard HBIOS result +code.

+

Style (E) is reserved to control the style of the cursor (blink, +visibility, etc.), but is not yet implemented.

+

Adjustments to the cursor style may or may not be possible for any given +video hardware and may be dependent on the active video mode.

+

Function 0x45 – Video Set Cursor Position (VDASCP)

+ + + + + + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x45A: Status
C: Video Unit
D: Row
E: Column
+

Reposition the cursor of the specified Video Unit (C) to the specified +Row (D) and Column (E). Specifying a row/column that exceeds the +boundaries of the display results in undefined behavior. Cursor +coordinates are 0 based (0,0 is the upper left corner of the display). +The Status (A) is a standard HBIOS result code.

+

Function 0x46 – Video Set Character Attribute (VDASAT)

+ + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x46A: Status
C: Video Unit
E: Attribute
+

Assign the specified character Attribute (E) code to be used for all +subsequent character writes/fills on the specified Video Unit (C). This +attribute is used to fill new lines generated by scroll operations. The +character attributes values are listed above. Note that a given video +display may or may not support any/all attributes. The Status (A) is a +standard HBIOS result code.

+

Function 0x47 – Video Set Character Color (VDASCO)

+ + + + + + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x47A: Status
C: Video Unit
D: Scope
E: Color
+

Assign the specified Color (E) code for character foreground/background. +If Scope (D) is 0, the specified color will be used for all subsequent +character writes/fills. This color is also used to fill new lines +generated by scroll operations. If Scope (D) is 1, then the specified +foreground/background color will be applied immediately to the entire +screen. Refer to the color code table above for a list of the available +color codes. Note that a given video display may or may not support +any/all colors. The Status (A) is a standard HBIOS result code.

+

Function 0x48 – Video Write Character (VDAWRC)

+ + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x48A: Status
C: Video Unit
E: Character
+

Write the Character (E) value to the display of the specified Video Unit +(C). The character is written starting at the current cursor position +and the cursor is advanced. If the end of the line is encountered, the +cursor will be advanced to the start of the next line. The display will +not scroll if the end of the screen is exceeded. The Status (A) is a +standard HBIOS result code.

+

Function 0x49 – Video Fill (VDAFIL)

+ + + + + + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x49A: Status
C: Video Unit
E: Character
HL: Count
+

Write the Character (E) value to the Video Unit (C) display the number +of times specified by Count (HL). Characters are written starting at the +current cursor position and the cursor is advanced by the number of +characters written. If the end of the line is encountered, the +characters will continue to be written starting at the next line as +needed. The display will not scroll if the end of the screen is +exceeded. Writing characters beyond the end of the screen results in +undefined behavior. The Status (A) is a standard HBIOS result code.

+

Function 0x4A – Video Copy (VDACPY)

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x4AA: Status
C: Video Unit
D: Source Row
E: Source Column
L: Count
+

Copy Count (L) bytes from the specified Video Unit (C) display Source +Row (D) and Source Column (E) to the current cursor position. The cursor +position is not updated. The maximum Count (L) value is 255. Copying +to/from overlapping areas is not supported and will have an undefined +behavior. The display will not scroll if the end of the screen is +exceeded. Copying beyond the active screen buffer area is not supported +and results in undefined behavior. The Status (A) is a standard HBIOS +result code.

+

Function 0x4B – Video Scroll (VDASCR)

+ + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x4BA: Status
C: Video Unit
E: Lines
+

Scroll the video display of the specified Video Unit (C) forward or +backwards by number of Lines (E) specified. If Lines (E) is positive, +then a forward scroll is performed. If Lines (E) contains a negative +number, then a reverse scroll will be performed. This function will +scroll the entire screen contents. New lines revealed during the scroll +operation will be filled with space characters (0x20) using the active +character attribute and color. The cursor position will not be +updated. The Status (A) is a standard HBIOS result code.

+

Function 0x4C – Video Keyboard Status (VDAKST)

+ + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x4CA: Status / Codes Pending
C: Video Unit
+

Return a count of the number of key Codes Pending (A) in the keyboard +buffer for the specified Video Unit (C). If it is not possible to +determine the actual number in the buffer, it is acceptable to return 1 +to indicate there are key codes available to read and 0 if there are +none available.

+

The value returned in register A is used as both a Status (A) code and +the return value. Negative values (bit 7 set) indicate a standard HBIOS +result (error) code. Otherwise, the return value represents the number +of key codes pending.

+

Function 0x4D – Video Keyboard Flush (VDAKFL)

+ + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x4DA: Status
C: Video Unit
+

If a keyboard buffer is in use on the Video Unit (C) specified, it +should be purged and all contents discarded. The Status (A) is a +standard HBIOS result code.

+

Function 0x4E – Video Keyboard Read (VDAKRD)

+ + + + + + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x4EA: Status
C: Video UnitC: Scancode
D: Keystate
E: Keycode
+

Read the next key data from keyboard of the specified Video Unit (C). If +a keyboard buffer is used, return the next Keycode in the buffer. If no +key data is available, this function will wait indefinitely for a +keypress. The Status (A) is a standard HBIOS result code.

+

The Scancode (C) value is the raw scancode from the keyboard for the +keypress. Scancodes are optional and may not be implemented by the +driver. The Scancode values are driver dependent. In the case of a PS/2 +keyboard driver, they should be the PS/2 scancode. Other keyboard +drivers may return values appropriate for their specific keyboard. If +the driver does not implement this, it should return 0 in C.

+

The Keystate (D) is a bitmap representing the value of all modifier keys +and shift states as they existed at the time of the keystroke. The +bitmap is defined as:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BitKeystate Indication
7Key pressed was from the num pad
6Caps Lock was active
5Num Lock was active
4Scroll Lock was active
3Windows key was held down
2Alt key was held down
1Control key was held down
0Shift key was held down
+

Not all of these bits may be relevant for all keyboards. Any bit that is +not relevant should be returned as 0.

+

The Keycode (E) is generally returned as appropriate ASCII values, if +possible. Special keys, like function keys and arrows, are returned as +reserved codes as described at the start of this section.

+

Function 0x4F – Read a character at current video position (VDARDC)

+ + + + + + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x4FA: Status
C: Video UnitE: Character
B: Color
E: Attribute
+

This function will return the character data from the current cursor +position of the display of the specified Video Unit (C). The data +returned includes the Character (E) value, the Color (B), and the +Attribute (E) corresponding to the current cursor position. If the +display does not support colors or attributes then this function will +return color white on black with no attributes. The ability to perform +this function may not be available for all video devices. The Status (A) +is a standard HBIOS result code.

+

Sound (SND)

+

Sound functions require that a Sound Unit number be specified in +register C. This is the logical device unit number assigned during the +boot process that identifies all sound devices uniquely.

+

All sound units are assigned a Device Type ID which indicates the +specific hardware device driver that handles the unit. The table below +enumerates these values.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Device TypeIDDescriptionDriver
SNDDEV_SN76489\$00SN76489 Programmable Sound Generatorsn76489.asm
SNDDEV_AY38910\$01AY-3-8910/YM2149 Programmable Sound Generatoray38910.asm
SNDDEV_BITMODE\$02Bit-bang Speakerspk.asm
SNDDEV_YM2612\$03YM2612 Programmable Sound Generatorym2612.asm
+

The Sound functions defer the actual programming of the sound chip until +the SNDPLAY function is called. You will call the volume and period/note +functions to preset the desired sound output, then call SNDPLAY when you +want the sound to change.

+

The Sound functions do not manage the duration of the sound played. A +sound will play indefinitely – the caller must implement an appropriate +timing mechanism to manage the playing of a series of sounds.

+
HBIOS B=51 C=00 L=80      ; Set volume to half level
+HBIOS B=53 C=00 HL=152    ; Select Middle C (C4)
+HBIOS B=54 C=00 D=01      ; Play note on Channel 1
+
+

Function 0x50 – Sound Reset (SNDRESET)

+ + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x50A: Status
C: Sound Unit
+

Reset the sound chip of specified Sound Unit (C). Turn off all sounds +and set volume on all channels to silence. The returned Status (A) is a +standard HBIOS result code.

+

Function 0x51 – Sound Volume (SNDVOL)

+ + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x51A: Status
C: Sound Unit
L: Volume
+

This function sets the sound chip Volume (L) for the specified Sound +Unit (C). Volume (L) is a binary value ranging from 0 (silence) to 255 +(maximum). The volume will be applied when the next SNDPLAY function is +invoked. The returned Status (A) is a standard HBIOS result code.

+

Note that not all sounds chips implement 256 volume levels. The driver +will scale the volume to the closest possible level the chip provides.

+

Function 0x52 – Sound Period (SNDPRD)

+ + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x52A: Status
C: Sound Unit
HL: Period
+

This function sets the sound chip Period (HL) for the specified Sound +Unit (C). The period will be applied when the next SNDPLAY function is +invoked. The returned Status (A) is a standard HBIOS result code.

+

The Period (HL) value is not a standardized value. The value is +programmed directly into the period or frequency register of the sound +chip. It is therefore a hardware dependent value. To play standardized +notes, use the SNDNOTE function.

+

Function 0x53 – Sound Note (SNDNOTE)

+ + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x53A: Status
C: Sound Unit
HL: Note
+

This function sets the frequency generated by the sound of the specified +Sound Unit (C). The frequency is standardized and is specified by using +values that correspond to musical notes. The frequency will be applied +when the next SNDPLAY function is invoked. The returned Status (A) is a +standard HBIOS result code.

+

The Note (HL) values correspond to quarter notes. Increasing/decreasing +the value by 4 results in a full note increment/decrement.
+Increasing/decreasing the value by 48 results in a full octave +increment/decrement. The value 0 corresponds to Bb/A# in octave 0.

+

The sound chip resolution and its oscillator limit the range and +accuracy of the notes played. The typical range of the AY-3-8910 is six +octaves: Bb2/A#2 to A7, where each value is a unique tone. Values above +and below can still be played but each quarter tone step may not result +in a note change.

+

The following table shows the mapping of the Note (HL) value to the +corresponding octave and note.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NoteOctave
01234567
C-856104152200248296
C#/Db-1260108156204252300
D-1664112160208256304
D#/Eb-2068116164212260308
E-2472120168216264312
F-2876124172220268316
F#/Gb-3280128176224272320
G-3684132180228276324
G#/Ab-4088136184232280328
A-4492140188236284332
A#/Bb04896144192240288336
B452100148196244292340
+

Function 0x54 – Sound Play (SNDPLAY)

+ + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x54A: Status
C: Sound Unit
D: Channel
+

This function applies the previously specified volume and frequency of +the specified Sound Unit (C) by programming the sound chip with the +appropriate values. The values are applied to the specified Channel (D) +of the chip. The returned Status (A) is a standard HBIOS result code.

+

Note that there is no duration for the sound output – the programmed +sound will be played indefinitely. It is up to the user to wait the +desired amount of time, then change or silence the sound output as +desired.

+

The number of channels available on a sound chip varies. It is up to the +caller to ensure that the appropriate number of channels are being +programmed.

+

Function 0x55 – Sound Query (SNDQUERY)

+ + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x55A: Status
C: Sound Unit
E: Subfunction
+

This function will return a variety of information for a specified Sound +Unit (C) according to the Subfunction (E) specified. The returned Status +(A) is a standard HBIOS result code.

+

SNDQUERY Subfunction 0x01 – Get count of audio channels supported (SNDQ_CHCNT)

+ + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x55A: Status
C: Sound UnitB: Tone Channels
E: 0x01C: Noise Channels
+

SNDQUERY Subfunction 0x02 – Get current volume setting (SNDQ_VOL)

+ + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x55A: Status
C: Sound UnitL: Volume
E: 0x02
+

SNDQdERY Subfunction 0x03 – Get current period setting (SNDQ_PERIOD)

+ + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x55A: Status
C: Sound UnitHL: Period
E: 0x03
+

SNDQUERY Subfunction 0x04 – Get device details (SNDQ_DEV)

+ + + + + + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x55A: Status
C: Sound UnitB: Driver Identity
E: 0x04HL: Ports
DE: Ports
+

This subfunction reports detailed device information for the specified +Sound Unit (C).

+

Driver Identity (B) reports the audio device type. Ports (HL & DE) +return relevant port addresses for the hardware specific to each device +type.

+

The following table defines the specific port information per device +type:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Audio IDValueDeviceReturned Registers
SND_SN764890x01SN76489E=Left channel port, L=Right channel port
SND_AY389100x02AY-3-8910D=Address port, E=Data port
SND_BITMODE0x03I/O PORTD=Address port, E=Bit mask
SND_YM26120x04YM2612Part 0: D=Address port, E=Data port
Part 1: D=Address port, L=Part 1 Data port
+

Function 0x56 – Sound Duration (SNDDUR)

+ + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x56A: Status
C: Sound Unit
HL: Duration
+

This function sets the Duration (HL) of the note to be played in +milliseconds for the specified Sound Unit (C). This function just sets +the duration, the actual duration is applied in the SNDPLAY function.

+

If the Duration (HL) is set to zero, then the SNDPLAY function will +operate in a non-blocking mode. i.e. a tone will start playing and the +play function will return. The tone will continue to play until the next +tone is played. If the Duration (HL) is greater than zero, the sound +will play for the duration defined in HL and then return.

+

***** Function Not Implemented ****

+

Function 0x57 – Sound Device (SNDDEVICE)

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x57A: Status
C: Sound UnitC: Device Attributes
D: Device Type
E: Device Number
H: Device Unit Mode
L: Device I/O Base Address
+

Reports device information about the specified Sound Unit (C). The +Status (A) is a standard HBIOS result code.

+

The Device Attributes (C) value is not yet defined.

+

Device Type (D) indicates the specific hardware driver that handles the +specified Sound Unit (C). Values are listed at the start of this +section. Device Number (E) indicates the physical device number assigned +per driver.

+

Device Mode (H) is used to indicate the variant of the chip or circuit +that is used by the specified unit. The Device I/O Base Address (L) +indicates the starting port address of the hardware interface that is +servicing the specified unit. Both of these values are considered driver +specific. Refer to the associated hardware driver for the values used.

+

Function 0x58 – Sound Beep (SNDBEEP)

+ + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0x58A: Status
C: Sound Unit
+

Play a beep tone on the specified Sound Unit (C). The beep will normally +be about 1/3 second in duration and the tone will be approximately B5.

+

Extension (EXT)

+

Helper (extension) functions that are not a core part of a BIOS.

+

Function 0xE0 – Calculate Slice (EXTSLICE)

+ + + + + + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0xE0A: Status
D: Disk UnitB: Device Attributes
E: SliceC: Media ID
DEHL: Sector Address
+

Report the Media ID (C), and Device Attributes (B) for the for media in +the specified Disk Unit (D), and for hard disks the absolute Sector +offset to the start of the Slice (E). The Status (A) is a standard HBIOS +result code.

+

This function extends upon Function 0x18 – Disk Media +(DIOMEDIA) for hard disk media by +scanning for a partition to determine if the disk uses HD512 or HD1K, +correctly reporting MID_HD or MID_HDNEW respectively. See the following +for some background Mapping to Media ID

+

It will also return the sector number of the first sector in the slice +if the slice number is valid. If the slice number is invalid (it wont +fix on the media) an error will be returned.

+

The slice calculation is performed by considering the partition start +(if it exists), the size of a slice for the given format type, and +ensuring that the slice fits within the media or partition size, taking +into consideration other partitions that may exist.

+

The Device Attributes (B) are the same as defined in Function 0x17 – +Disk Device (DIODEVICE)

+

If the Unit specified is not a hard disk the Media ID will be returned +and the slice parameter ignored. If there is no media in device, or the +slice number is invaid (Parameter Out Of Range) the function will return +an error status.

+

**NOTE: This function was placed in HBIOS to be shared between the +diffeent CP/M varients supported by RomWBW. It is not strictly a BIOS +function, and may be moved in future.

+

System (SYS)

+

Function 0xF0 – System Reset (SYSRESET)

+ + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0xF0A: Status
C: Subfunction
+

This function performs various forms of a system reset depending on the +value of Subfunction (C):

+

Soft Reset (0x00):
+Perform a soft reset of HBIOS. Releases all HBIOS memory allocated by +current OS. Does not reinitialize physical devices.

+

Warm Start (0x01):
+Warm start the system returning to the boot loader prompt. Does not +reinitialize physical devices.

+

Cold Start (0x02):
+Perform a system cold start (like a power on). All devices are +reinitialized.

+

User Restart (0x03):
+Perform a video terminal reset. Terminal emulation and visual display +systems are reset.

+

The Status (A) is a standard HBIOS result code.

+

Function 0xF1 – System Version (SYSVER)

+ + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0xF1A: Status
C: ReservedDE: Version
L: Platform
+

This function will return the HBIOS Version (DE) number and Platform (L) +identifier. The Status (A) is a standard HBIOS result code.

+

The Version (DE)number is encoded as BCD where the 4 digits are:

+

[Major Version][Minor Version][Patch Level][Build Number]

+

So, for example, a Version (DE) number of 0x3102 would indicate version +3.1.0, build 2.

+

The hardware Platform (L) is identified as follows:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameId**Platform **
PLT_SBC1ECB Z80 SBC
PLT_ZETA2ZETA Z80 SBC
PLT_ZETA23ZETA Z80 V2 SBC
PLT_N84N8 (HOME COMPUTER) Z180 SBC
PLT_MK45MARK IV
PLT_UNA6UNA BIOS
PLT_RCZ807RCBUS W/ Z80
PLT_RCZ1808RCBUS W/ Z180
PLT_EZZ809EASY/TINY Z80
PLT_SCZ18010SMALL COMPUTER CENTRAL Z180
PLT_DYNO11DYNO MICRO-ATX MOTHERBOARD
PLT_RCZ28012RCBUS W/ Z280
PLT_MBC13NHYODYNE MULTI-BOARD COMPUTER
PLT_RPH14RHYOPHYRE GRAPHICS SBC
PLT_Z80RETRO15Z80 RETRO COMPUTER
PLT_S10016S100 COMPUTERS Z180
PLT_DUO17DUODYNE Z80 SYSTEM
PLT_HEATH18HEATHKIT H8 Z80 SYSTEM
PLT_EPITX19Z180 MINI-ITX
PLT_MON20MONSPUTER (DEPRECATED)
PLT_GMZ18021GENESIS Z180 SYSTEM
PLT_NABU22NABU PC W/ ROMWBW OPTION BOARD
PLT_FZ8023S100 FPGA Z80
PLT_RCEZ8024RCBUS W/ eZ80
+

For more information on these platforms see RomWBW +Hardware

+

Function 0xF2 – System Set Bank (SYSSETBNK)

+ + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0xF2A: Status
C: Bank IDC: Prior Bank ID
+

Activates the specified memory Bank ID (C) and returns the Prior Bank ID +(C).

+

The function must be invoked from code located in the upper 32K and +the stack must be in the upper 32K. The Status (A) is a standard +HBIOS result code.

+

If the system is using interrupt mode 1 interrupts, the you must +take steps to ensure interrupts are properly handled. You generally have +two choices:

+
    +
  • Disable interrupts while the User Bank is switched out
  • +
  • Duplicate the interrupt mode 1 vector from the User Bank into the bank + you are switching to.
  • +
+

If the User Bank has been switched out, you will not be able to invoke +the HBIOS API functions using an RST 08 instruction. You can use the +alternative mechanism using CALL $FFF0 as described in +Invocation.

+

Function 0xF3 – System Get Bank (SYSGETBNK)

+ + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0xF3A: Status
C: Bank ID
+

Returns the currently active Bank ID (C). The Status (A) is a standard +HBIOS result code.

+

Function 0xF4 – System Set Copy (SYSSETCPY)

+ + + + + + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0xF4A: Status
D: Destination Bank ID
E: Source Bank ID
HL: Byte Count
+

Prepare for a subsequent interbank memory copy (SYSBNKCPY) function call +by setting the Source Bank ID (E), Destination Bank ID (D), and Byte +Count (HL) to be copied. The bank ID’s are not range checked and must be +valid for the system in use. The Status (A) is a standard HBIOS result +code.

+

No bytes are copied by this function. The SYSBNKCPY function must be +called to actually perform the copy. The values setup by this function +will remain unchanged until another call is make to this function. So, +after calling SYSSETCPY, you may make multiple calls to SYSBNKCPY as +long as you want to continue to copy between the already established +Source/Destination Banks and the same size copy is being performed.

+

Function 0xF5 – System Bank Copy (SYSBNKCPY)

+ + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0xF5A: Status
DE: Destination AddressDE: New Destination Address
HL: Source AddressHL: New Source Address
+

Copy a block of memory between banks. The Source Bank, Destination Bank, +and Byte Count to copy must be established with a prior call to +SYSSETCPY. However, it is not necessary to call SYSSETCPY prior to +subsequent calls to SYSBNKCPY if the source/destination banks and copy +length do not change.

+

On return, the New Destination Address (DE) will be value of the +original Destination Address (DE) incremented by the count of bytes +copied. Likewise for the New Source Address (HL). This allows iterative +invocations of this function to continue copying where the prior +invocation left off.

+

The Status (A) is a standard HBIOS result code.

+

WARNINGS:

+
    +
  • +

    This function is inherently dangerous and does not prevent you from + corrupting critical areas of memory. Use with extreme caution.

    +
  • +
  • +

    Overlapping source and destination memory ranges are not supported and + will result in undetermined behavior.

    +
  • +
  • +

    Copying of byte ranges that cross bank boundaries is undefined.

    +
  • +
+

Function 0xF6 – System Alloc (SYSALLOC)

+ + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0xF6A: Status
HL: Block SizeHL: Block Address
+

This function will attempt to allocate a Block Size (HL) bytes block of +memory from the internal HBIOS heap. The HBIOS heap resides in the HBIOS +bank in the area of memory left unused by HBIOS. If the allocation is +successful, the Block Address (HL) of the allocated memory block is +returned in HL. You will typically need to use the SYSBNKCPY function to +read/write the allocated memory. The Status (A) is a standard HBIOS +result code.

+

Function 0xF7 – System Free (SYSFREE)

+ + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0xF7A: Status
HL: Block Address
+

*** Function Not Implemented ***

+

Note that all allocated memory can be freed by calling the SYSRESET +function with a subfunction code of 0x00 (Soft Reset).

+

Function 0xF8 – System Get (SYSGET)

+ + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0xF8A: Status
C: Subfunction
+

This function will report various system information based on the +sub-function value. The following lists the subfunctions available along +with the registers/information utilized. The Status (A) is a standard +HBIOS result code.

+

SYSGET Subfunction 0x00 – Get Character Device Unit Count (CIOCNT)

+ + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0xF8A: Status
C: 0x00E: Count
+

Return the Count (E) of character device units. The Status (A) is a +standard HBIOS result code.

+

SYSGET Subfunction 0x01 – Get Serial Unit Function (CIOFN)

+ + + + + + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0xF8A: Status
C: 0x01HL: Function Address
D: FunctionDE: Unit Data Address
E: Unit
+

This function will lookup the actual driver function address and unit +data address inside the HBIOS driver. On entry, place the CIO function +number to lookup in D and the CIO unit number in E. On return, HL will +contain the address of the requested function in the HBIOS driver (in +the HBIOS bank). DE will contain the associated unit data address (also +in the HBIOS bank). See Appendix A for details. The returned Status (A) +is a standard HBIOS result code.

+

This function can be used to speed up HBIOS calls by looking up the +function and data address for a specific driver function. After this, +the caller can use interbank calls directly to the function in the +driver which bypasses the overhead of the normal function invocation +lookup.

+

SYSGET Subfunction 0x10 – Get Disk Device Unit Count (DIOCNT)

+ + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0xF8A: Status
C: 0x10E: Count
+

Return the Count (E) of disk device units. The Status (A) is a standard +HBIOS result code.

+

SYSGET Subfunction 0x11 – Get Disk Unit Function (DIOFN)

+ + + + + + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0xF8A: Status
C: 0x11HL: Function Address
D: FunctionDE: Unit Data Address
E: Unit
+

This function will lookup the actual driver function address and unit +data address inside the HBIOS driver. On entry, place the DIO function +number to lookup in D and the DIO unit number in E. On return, HL will +contain the address of the requested function in the HBIOS driver (in +the HBIOS bank). DE will contain the associated unit data address (also +in the HBIOS bank). See Appendix A for details. The returned Status (A) +is a standard HBIOS result code.

+

This function can be used to speed up HBIOS calls by looking up the +function and data address for a specific driver function. After this, +the caller can use interbank calls directly to the function in the +driver which bypasses the overhead of the normal function invocation +lookup.

+

SYSGET Subfunction 0x20 – Get RTC Device Unit Count (RTCCNT)

+ + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0xF8A: Status
C: 0x20E: Count
+

Return the Count (E) of RTC device units. The Status (A) is a standard +HBIOS result code.

+

SYSGET Subfunction 0x40 – Get Video Device Unit Count (VDACNT)

+ + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0xF8A: Status
C: 0x40E: Count
+

Return the Count (E) of video device units. The Status (A) is a standard +HBIOS result code.

+

SYSGET Subfunction 0x41 – Get Video Unit Function (VDAFN)

+ + + + + + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0xF8A: Status
C: 0x41HL: Function Address
D: FunctionDE: Unit Data Address
E: Unit
+

This function will lookup the actual driver function address and unit +data address inside the HBIOS driver. On entry, place the VDA function +number to lookup in D and the VDA unit number in E. On return, HL will +contain the address of the requested function in the HBIOS driver (in +the HBIOS bank). DE will contain the associated unit data address (also +in the HBIOS bank). See Appendix A for details. The returned Status (A) +is a standard HBIOS result code.

+

This function can be used to speed up HBIOS calls by looking up the +function and data address for a specific driver function. After this, +the caller can use interbank calls directly to the function in the +driver which bypasses the overhead of the normal function invocation +lookup.

+

SYSGET Subfunction 0x50 – Get Sound Device Unit Count (SNDCNT)

+ + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0xF8A: Status
C: 0x50E: Count
+

Return the Count (E) of sound device units. The Status (A) is a standard +HBIOS result code.

+

SYSGET Subfunction 0x51 – Get Sound Unit Function (SNDFN)

+ + + + + + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0xF8A: Status
C: 0x51HL: Function Address
D: FunctionDE: Unit Data Address
E: Unit
+

This function will lookup the actual driver function address and unit +data address inside the HBIOS driver. On entry, place the SND function +number to lookup in D and the SND unit number in E. On return, HL will +contain the address of the requested function in the HBIOS driver (in +the HBIOS bank). DE will contain the associated unit data address (also +in the HBIOS bank). See Appendix A for details. The returned Status (A) +is a standard HBIOS result code.

+

This function can be used to speed up HBIOS calls by looking up the +function and data address for a specific driver function. After this, +the caller can use interbank calls directly to the function in the +driver which bypasses the overhead of the normal function invocation +lookup.

+

SYSGET Subfunction 0xC0 – Get Switches (SWITCH)

+ + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0xF8A: Status
C: 0xC0HL: Switch Value
D: Switch Key
+

This function will return the current value (HL) of the switch (D) from +NVRAM.

+

Switches may be returned as a 16 bit (HL) or 8 bit (L) value. It is up +to the caller to process the returned value correctly. Note for Switch +0xFF (status) the returned value is primarily in the Status (A) +register.

+

Errors are signaled in the return by setting the NZ flag. When set the +(A) register may contain an error code, but this code does not conform +to RomWBW standard

+

Success is indicated by setting the Z flag

+

For a description of switches please see RomWBW NVRAM +Configuration

+

SYSGET Subfunction 0xD0 – Get Timer Tick Count (TIMER)

+ + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0xF8A: Status
C: 0xD0DEHL: Tick Count
C: Frequency
+

Return the value of the global system timer Tick Count (DEHL). This is a +double-word binary value. The frequency of the system timer in Hertz is +returned in Frequency (C). The returned Status (A) is a standard HBIOS +result code.

+

The tick count is a 32 bit binary value. It will rollover to zero if the +maximum value for a 32 bit number is reached.

+

Note that not all hardware configuration have a system timer. You can +determine if a timer exists by calling this function repeatedly to see +if it is incrementing.

+

SYSGET Subfunction 0xD1 – Get Seconds Count (SECONDS)

+ + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0xF8A: Status
C: 0xD1DEHL: Seconds Count
C: Remainder Ticks
+

Return the Seconds Count (DEHL) with the number of seconds that have +elapsed since the system was started. This is a double-word binary +value. Additionally, Remainder Ticks (C) is returned and contains the +number of ticks that have elapsed within the current second.

+

Note that Remainder Ticks (C) will have a value from 0 to 49 since there +are 50 ticks per second. So, Remainder Ticks does not represent a +fraction of the current second. Remainder Ticks (C) can be doubled to +derive the hundredths of milliseconds elapsed within the current second.

+

The availability of the Seconds Count (DEHL) is dependent on having a +system timer active. If the hardware configuration has no system timer, +then Seconds Count (DEHL) will not increment.

+

SYSGET Subfunction 0xE0 – Get Boot Information (BOOTINFO)

+ + + + + + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0xF8A: Status
C: 0xE0L: Boot Bank ID
D: Boot Disk Unit
E: Boot Disk Slice
+

This function returns information about the most recent boot operation +performed. It includes the Boot Bank ID (L), the Boot Disk Unit (D), and +the Boot Disk Slice (E). The returned Status (A) is a standard HBIOS +result code.

+

SYSGET Subfunction 0xF0 – Get CPU Information (CPUINFO)

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0xF8A: Status
C: 0xF0H: Z80 CPU Variant
L: CPU Speed MHz
DE: CPU Speed KHz
BC: Oscillator Speed KHz
+

This function returns information about the active CPU environment. The +Z80 CPU Variant (H) will be one of: 0=Z80, 1=Z180, 2=Z180-K, 3=Z180-N, +4=Z280. The current CPU speed is provided as both CPU Speed MHz (L) and +CPU Speed KHz (DE). The raw oscillator speed is provided as Oscillator +Speed KHz (BC). The returned Status (A) is a standard HBIOS result code.

+

SYSGET Subfunction 0xF1 – Get Memory Information (MEMINFO)

+ + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0xF8A: Status
C: 0xF1D: ROM Bank Count
E: RAM Bank Count
+

This function returns the systems ROM Bank Count (D) and RAM Bank Count +(E). Each bank is 32KB by definition. The returned Status (A) is a +standard HBIOS result code.

+

SYSGET Subfunction 0xF2 – Get Bank Information (BNKINFO)

+ + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0xF8A: Status
C: 0xF2D: BIOS Bank ID
E: User Bank ID
+

Certain memory banks within a RomWBW system are special. The exact bank +id for each of these varies depending on the configuration of the +system. This function can be used to determine the BIOS Bank ID (D) and +the User Bank ID (E). The returned Status (A) is a standard HBIOS result +code.

+

SYSGET Subfunction 0xF3 – Get CPU Speed (CPUSPD)

+ + + + + + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0xF8A: Status
C: 0xF3L: Clock Mult
D: Memory Wait States
E: I/O Wait States
+

This function will return the running CPU speed attributes of a system. +The Clock Mult (L) returned indicates the frequency multiple being +applied to the raw oscillator clock. If is defined as: 0=Half, 1=Full, +and 2=Double. The wait states for the system are also provided as Memory +Wait States (D) and I/O Wait States (E). The value of Memory Wait States +(D) is the actual number of wait states, not the number of wait states +added. The returned Status (A) is a standard HBIOS result code.

+

SYSGET Subfunction 0xF4 – Get Front Panel Swithes (PANEL)

+ + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0xF8A: Status
C: 0xF4L: Switches
+

This function will return the current value of the switches (L) from the +front panel of the system. If no front panel is available in the system, +the returned Status (A) will indicate a No Hardware error.

+

SYSGET Subfunction 0xF5 – Get Application Banks Information (APPBNKS)

+ + + + + + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0xF8A: Status
C: 0xF5H: App Banks Start ID
L: App Banks Count
E: Bank Size
+

HBIOS may be configured to reserve a number of RAM memory banks that +will be available for application use. This function returns information +about the RAM memory banks currently available for application use. The +function provides the bank id of the first available application bank +(H) and the count of banks available (L). It also returns the size of a +bank expressed as a number of 256-byte pages (E). The returned Status +(A) is a standard HBIOS result code.

+

The application banks are always a contiguous set of banks, so the App +Banks Start ID can be incremented to address additional banks up to the +limit indicated by App Banks Count. If the App Banks Count is zero, then +there are no application banks available (regardless of the value of App +Banks Start ID).

+

HBIOS does not provide any mechanism to reserve application banks. Any +concept of allocation of application banks must be implemented within +the OS or application.

+

This function does not change the current bank selected. You must use +Function 0xF2 – System Set Bank +(SYSSETBNK) or the proxy +function Bank Select (BNKSEL) for this. Be sure +to observe the warnings in the description of this function.

+

Function 0xF9 – System Set (SYSSET)

+ + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0xF9A: Status
C: Subfunction
+

This function will set various system parameters based on the +sub-function value. The following lists the subfunctions available along +with the registers/information utilized. The Status (A) is a standard +HBIOS result code.

+

SYSSET Subfunction 0xC0 – Set Switches (SWITCH)

+ + + + + + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0xF9A: Status
C: 0xC0
D: Switch Key
HL: Switch Value
+

This function will set the value (HL) into the switch (D) and store it +into NVRAM.

+

Switches may be passed as a 16 bit (HL) or 8 bit (L) value. It is up to +the caller to send the value correctly. Note for Switch 0xFF (reset) the +value (HL) is ignored

+

Errors are signalled in the return by setting the NZ flag. When set the +(A) register may contain an error code, but this code does not conform +to RomWBW standard

+

Success is indicated by setting the Z flag

+

For a description of switches please see RomWBW NVRAM +Configuration

+

SYSSET Subfunction 0xD0 – Set Timer Tick Count (TIMER)

+ + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0xF9A: Status
C: 0xD0DEHL: Timer Tick Count
+

This function will explicitly set the system Timer Tick Count (DEHL) +value. DEHL is a double-word binary value. The Status (A) is a standard +HBIOS result code.

+

SYSSET Subfunction 0xD1 – Set Seconds Count (SECONDS)

+ + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0xF9A: Status
C: 0xD1
DEHL: Seconds Count
+

This function will explicitly set the system Seconds Count (DEHL) value. +DEHL is a double-word binary value. The Status (A) is a standard HBIOS +result code.

+

SYSSET Subfunction 0xE0 – Set Boot Information (BOOTINFO)

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0xF9A: Status
C: 0xE0
L: Boot Bank ID
D: Boot Disk Unit
E: Boot Disk Slice
+

This function sets information about the most recent boot operation +performed. It includes the Boot Bank ID (L), the Boot Disk Unit (D), and +the Boot Disk Slice (E). The returned Status (A) is a standard HBIOS +result code.

+

SYSSET Subfunction 0xF3 – Set CPU Speed (CPUSPD)

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0xF9A: Status
C: 0xF3
L: Clock Mult
D: Memory Wait States
E: I/O Wait States
+

This function will modify the running CPU speed attributes of a system. +Note that it is frequently impossible to tell if a system is capable of +dynamic speed changes. This function makes the changes blindly. You can +specify 0xFF for either of the wait state settings to have them left +alone. If an attempt is made to change the speed of a system that is +definitely incapable of doing so, then an error result is returned. The +returned Status (A) is a standard HBIOS result code.

+

The function will attempt to set the CPU speed based on the Clock Mult +(L) value: 0=Half, 1=Full, 2=Double. Memory Wait States (D) and I/O Wait +States (E) will be set if possible. The value of Memory Wait States (D) +is the actual number of wait states, not the number of wait states +added.

+

Some peripherals are dependent on the CPU speed. For example, the Z180 +ASCI baud rate and system timer are derived from the CPU speed. The Set +CPU Speed function will attempt to adjust these peripherals for correct +operation after modifying the CPU speed. However, in some cases this may +not be possible. The baud rate of ASCI ports have a limited set of +divisors. If there is no satisfactory divisor to retain the existing +baud rate under the new CPU speed, then the baud rate of the ASCI +port(s) will be affected.

+

SYSSET Subfunction 0xF4 – Set Front Panel LEDs (PANEL)

+ + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0xF9A: Status
C: 0xF4
L: LEDs
+

This function will set the front panel LEDs based on the bits in L. If +no front panel is available in the system, the returned Status (A) will +indicate a No Hardware error.

+

Function 0xFA – System Peek (SYSPEEK)

+ + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0xFAA: Status
D: Bank IDE: Byte Value
HL: Memory Address
+

This function retrieves and returns the Byte Value from the specified +Bank ID (D) and Memory Address (HL). The bank specified is not range +checked. The Status (A) is a standard HBIOS result code.

+

Function 0xFB – System Poke (SYSPOKE)

+ + + + + + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0xFBA: Status
D: Bank ID
HL: Memory Address
E: Byte Value
+

This function sets the Byte Value (E) in the specified Bank ID (D) and +Memory Address (HL). The bank specified is not range checked. The Status +(A) is a standard HBIOS result code.

+

Function 0xFC – System Interrupt Management (SYSINT)

+ + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0xFCA: Status
C: Subfunction
+

This function allows the caller to query information about the interrupt +configuration of the running system and allows adding or hooking +interrupt handlers dynamically. Register C is used to specify a +sub-function. Additional input and output registers may be used as +defined by the sub-function. The Status (A) is a standard HBIOS result +code.

+

Note that during interrupt processing, the lower 32K of CPU address +space will contain the RomWBW HBIOS code bank, not the lower 32K of +application TPA. As such, a dynamically installed interrupt handler does +not have access to the lower 32K of TPA and must be careful to avoid +modifying the contents of the lower 32K of memory. Invoking RomWBW HBIOS +functions within an interrupt handler is not supported.

+

Interrupt handlers are different under IM1 and IM2.

+

Interrupt Mode 1:
+The new interrupt handler is responsible for chaining (JP) to the +previous vector if the interrupt is not handled. If the interrupt is +handled, the new handler may simply return (RET). When chaining to the +previous interrupt handler, ZF must be set if interrupt is handled and +ZF cleared if not handled. The interrupt management framework takes care +of saving and restoring AF, BC, DE, HL, and IY. Any other registers +modified must be saved and restored by the interrupt handler.

+

Interrupt Mode 2:
+The new interrupt handler may either replace or hook the previous +interrupt handler. To replace the previous interrupt handler, the new +handler just returns (RET) when done. To hook the previous handler, the +new handler can chain (JP) to the previous vector. Note that initially +all IM2 interrupt vectors are set to be handled as “BAD” meaning that +the interrupt is unexpected. In most cases, you do not want to chain to +the previous vector because it will cause the interrupt to display a +“BAD INT” system panic message.

+

The interrupt framework will take care of issuing an EI and RETI +instruction. Do not put these instructions in your new handler. +Additionally, interrupt management framework takes care of saving and +restoring AF, BC, DE, HL, and IY. Any other registers modified must be +saved and restored by the interrupt handler.

+

If the caller is transient, then the caller must remove the new +interrupt handler and restore the original one prior to termination. +This is accomplished by calling this function with the Interrupt Vector +set to the Previous Vector returned in the original call.

+

The caller is responsible for disabling interrupts prior to making an +INTSET call and enabling them afterwards. The caller is responsible for +ensuring that a valid interrupt handler is installed prior to enabling +any hardware interrupts associated with the handler. Also, if the +handler is transient, the caller must disable the hardware interrupt(s) +associated with the handler prior to uninstalling it.

+

SYSINT Subfunction 0x00 – Interrupt Info (INTINF)

+ + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0xFCA: Status
C: 0x00D: Interrupt Mode
E: IVT Size
+

Return current Interrupt Mode (D) of the system. Also return the number +of Interrupt Vector Table (IVT) entries in IVT (E). For IM1, the size of +the table is the number of vectors chained together. For IM2, the size +of the table is the number of slots in the vector table. The Status (A) +is a standard HBIOS result code.

+

SYSINT Subfunction 0x10 – Get Interrupt (INTGET)

+ + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0xFCA: Status
C: 0x10HL: IVT Address
E: IVT Index
+

This function will return the IVT Address (HL) of the current interrupt +vector for the specified IVT Index (C). The Status (A) is a standard +HBIOS result code.

+

SYSINT Subfunction 0x20 – Set Interrupt (INTSET)

+ + + + + + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
B: 0xFCA: Status
C: 0x20HL: Previous Interrupt Address
E: IVT Index
HL: Interrupt Address
+

This function will set a new Interrupt Address (HL) at the IVT Index (E) +specified. On return, the Previous Interrupt Address (HL) will be +provided.

+

Proxy Functions

+

The following special functions are implemented inside of the HBIOS +proxy area at the top of RAM. They do not cause a bank switch and are, +therefore, much faster than their corresponding HBIOS API functions.

+

The functions are invoked via the following dedicated jump table:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FunctionAddress** Equate **
Invoke HBIOS Function (INVOKE)0xFFF0HB_INVOKE
Bank Select (BNKSEL)0xFFF3HB_BNKSEL
Bank Copy (BNKCPY)0xFFF6HB_BNKCPY
Bank Call (BNKCALL)0xFFF9HB_BNKCALL
+

The function addresses are also defined as equates in hbios.inc. It is +suggested that you use the equates when possible.

+

To use the functions, you may either call or jump to them. Some +examples:

+
        CALL    $FFF0
+        JP      $FFF3
+        CALL    HB_BNKCPY
+
+

These functions are inherently dangerous and generally not value +checked. Use with extreme caution.

+

Invoke HBIOS Function (INVOKE)

+

Address 0xFFF0

+

This function is an alternate mechanism for invoking the normal HBIOS +API functions. The parameters and return values are as documented above. +To put it another way, CALL $FFF0 is equivalent to RST 08, but it +can be used in any scenario when the normal bank is not selected.

+

Bank Select (BNKSEL)

+

Address 0xFFF3

+ + + + + + + + + + + + + +
Entry ParametersReturned Values
A: Bank ID
+

This function will select the memory bank identified by Bank ID (A). +Register AF is destroyed. All other registers are preserved.

+

The warnings described in Function 0xF2 – System Set Bank +(SYSSETBNK) should be +observed.

+

Bank Copy (BNKCPY)

+

Address 0xFFF6

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
HL: Source AddressHL: Ending Source Address
DE: Destination AddressDE: Ending Destination Address
BC: CountBC: 0
HB_SRCBNK: Source Bank ID
HB_DSTBNK: Destination Bank ID
+

This function will copy Count (BC) bytes from Source Address (HL) in +Source Bank ID (HB_SRCBNK) to Destination Address (DE) in Destination +Bank ID (HB_DSTBNK). The HB_SRCBNK and HB_DSTBNK fields are dedicated +locations in the proxy. These locations are defined in hbios.inc:

+
    +
  • Source Bank ID: HB_SRCBNK = \$FFE4
  • +
  • Destination Bank ID: HB_DSTBNK = \$FFE7
  • +
+

The Source Bank ID and Destination Bank ID values must be populated in +the specified addresses before calling this function.

+

During processing, HL and DE, will be incremented. At termination, HL +and DE will contain the “next” source/destination addresses that would +be copied. This allows this function to be invoked repeatedly to copy +continuous blocks of data.

+

Register AF is destroyed by this function. Register BC will be 0.

+

Bank Call (BNKCALL)

+

Address 0xFFF9

+ + + + + + + + + + + + + + + + + +
Entry ParametersReturned Values
A: Target Bank ID
IX: Target Address
+

This function will perform a function call to a routine in another bank. +It does this by selecting the Target Bank ID (A) and then calling the +Target Address (IX). On return from the target function, the originally +active bank is selected.

+

Register usage is determined by the routine that is called.

+

Since a different bank will be selected while the target function is +active, the warnings described in Function 0xF2 – System Set Bank +(SYSSETBNK) should be +observed.

+

Errors and diagnostics

+

ROMWBW tries to provide useful information when a run time or build time +error occurs. Many sections of the code also have code blocks that can +be enable to aid in debugging and in some cases the level of reporting +detail can be customized.

+

Run Time Errors

+

PANIC

+

A panic error indicates a non-recoverable error. The processor status is +displayed on the console and interrupts are disabled and execution is +halted. A cold boot or reset is required to restart.

+

Example error message:

+
>>> PANIC: @06C4[DFA3:DFC3:0100:F103:04FC:0000:2B5E]
+
+*** System Halted ***
+
+

The format of the information provided is

+

@XXXX [-AF-:-BC-:-DE-:-HL-:-SP-:-IX-:-IY-]

+

Where @XXXX is the address the panic was called from. The other +information is the CPU register contents.

+

Possible reasons a PANIC may occur are:

+
    +
  • RAM Bank range error when attempting a read or write to a RAM disk.
  • +
  • Sector read function has not been setup but a read was attempted.
  • +
  • An interrupt vector has not been set up when an interrupt was + received.
  • +
  • There was an attempt to add more devices than the device table had + room for.
  • +
  • An illegal SD card command was encountered.
  • +
+

The @XXXX memory address can be cross referenced with the build source +code to identify which section of the software or hardware caused the +fault.

+

SYSCHK

+

A syschk error is identified when an internal error is detected. When +this occurs an error code is returned to the calling program in the A +register. A non-zero result indicates an error.

+

Syschk errors may be reported to the console. Whether this occurs +depends on the value of the diagnosis level equate DIAGLVL. By default +syschk errors are not reported to the console.

+

If the diagnosis level is set to display the diagnosis information, then +memory address, register dump and error code is displayed. A key +difference with the PANIC error is that execution may be continued.

+

Example error message:

+

>>> SYSCHK: @06C4 [DFA3:DFC3:0100:F103:04FC:0000:2B5E] FD Continue +(Y/N)

+

The format of the information provided is similar the PANIC report.

+

@XXXX [-AF-:-BC-:-DE-:-HL-:-SP-:-IX-:-IY-] YY

+

The syschk error codes YY is returned in the A register.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ErrorCode YY
Success0x00
Undefined Error0xFF
Function Not Implemented0xFE
Invalid Function0xFD
Invalid Unit Number0xFC
Out Of Memory0xFB
Parameter Out Of Range0xFA
Media Not Present0xF9
Hardware Not Present0xF8
I/O Error0xF7
Write Request To Read-Only Media0xF6
Device Timeout0xF5
Invalid Configuration0xF4
Internal Error0xF3
+

Error Level reporting

+

placeholder

+

Build time errors

+

Build chain tool errors

+

place holder

+

Assembly time check errors

+

placeholder

+

Diagnostics

+

Diagnostic LEDs

+

Progress through the boot and initialization process can be difficult to +monitor due to the lack of console or video output. Access to these +output devices does not become available until late the in the boot +process. If these output devices are also involved with the issue trying +to be resolved then trouble shooting is even more difficult.

+

ROMWBW can be configured to display boot progress with the assistance of +additional hardware. This can take the form of a front panel LED display +or LED breakout debugging board connected to an 8-bit output port. Or it +can utilize existing platform status LEDS.

+

As the boot code executes, the LED output display is updated to indicate +the execution progress.

+

Platforms that have these capabilities built in have them enabled by +default.

+

Front Panel display

+

A LED front panel or breakout board needs to be connected the computers +data, reset and port select lines.

+

To enable this option the following settings can be made in the +platforms custom configuration file.

+
FPLED_ENABLE    .SET    TRUE           ; ENABLE FRONT PANEL
+
+

Custom hardware can be configured with :

+
FPLED_IO    .SET    $nn         ; USE PORT ADDRESS nn
+FPLED_INV   .SET    FALSE       ; INVERTED LED BITS
+
+

Platform Status LEDS

+

These status LEDs use preexisting status LEDs on each platform.

+

Enable using:

+
LEDENABLE   .SET    TRUE            ; ENABLES STATUS LED
+
+

Customize using:

+
LEDMODE     .SET    LEDMODE_STD     ; LEDMODE_[STD|SC|RTC|NABU]
+LEDPORT     .SET    $nn             ; STATUS LED PORT ADDRESS
+
+

The following table shows the ROMWBW process steps in relation to the +panel display.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PANELRomWBW Processes
........Initial boot
Jump to start address
Disable interrupts
Set interrupt mode
Initialize critical ports and baud rate
.......OSetup initial stack
Memory manager and CPU configuration
Set top bank to be RAM
......OOGet and save battery condition
Install HBIOS proxy in upper memory
If platform is MBC reconfigure memory manager
Setup “ROMLESS” HBIOS image or …
Copy HBIOS from ROM to RAM if RAM flag not set
Jump to HBIOS in RAM
Set running in RAM flag
.....OOOFinalize configuration for running in RAM
Check battery condition
Check for recovery mode boot
....OOOOIdentify CPU type
...OOOOOSet cpu oscillator speed
Setup counter-timers
Setup heap
..OOOOOOPreconsole initialization
.OOOOOOOBoot delay
Set boot console device
Bios announcement
OOOOOOOODisplay platform information
Display memory configuration
Display CPU family
Verify ROM checksum
Report battery condition
Perform device driver initialization
Report watchdog status
Mark HBIOS heap so it is preserved
Switch from boot console to CRT if active
Display device summary
Execute boot loader
+

Appendix A Driver Instance Data fields

+

This section is a work in progress…

+

The following section outlines the read only data referenced by the +SYSGET, subfunctions xxxFN for specific drivers.

+

TMS9918 Driver:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameOffsetBytesDescription
PPIA01PPI PORT A
PPIB11PPI PORT B
PPIC21PPI PORT C
PPIX31PPI CONTROL PORT
DATREG41IO PORT ADDRESS FOR MODE 0
CMDREG51IO PORT ADDRESS FOR MODE 1
Below are the register mirror values
that HBIOS used for initialisation
REG. 061\$00 - NO EXTERNAL VID
REG. 171\$50 or \$70 - SET MODE 1 and interrupt if enabled
REG. 281\$00 - PATTERN NAME TABLE := 0
REG. 391\$00 - NO COLOR TABLE
REG. 4101\$01 - SET PATTERN GENERATOR TABLE TO \$800
REG. 5111\$00 - SPRITE ATTRIBUTE IRRELEVANT
REG. 6121\$00 - NO SPRITE GENERATOR TABLE
REG. 7131\$F0 - WHITE ON BLACK
DCNTL*141Z180 DMA/WAIT CONTROL
+
    +
  • ONLY PRESENT FOR Z180 BUILDS
  • +
+
+
+ + + + + + + + + + + diff --git a/UserGuide/Graphics/BankSwitchedMemory.svg b/UserGuide/Graphics/BankSwitchedMemory.svg new file mode 100644 index 00000000..ef18a94e --- /dev/null +++ b/UserGuide/Graphics/BankSwitchedMemory.svg @@ -0,0 +1,366 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Page-1 + + Data block.13 + + Sheet.14 + + + + Sheet.15 + + + + Sheet.16 + + + + + Data block.9 + + Sheet.10 + + + + Sheet.11 + + + + Sheet.12 + + + + + Data block + + Sheet.6 + + + + Sheet.7 + + + + Sheet.8 + + + + + Sheet.2 + $FE00 + + + $FE00 + + Sheet.3 + $D000 + + + $D000 + + Sheet.17 + $8000 + + + $8000 + + 3D stack middle + + Sheet.19 + + + + Sheet.20 + + + + + 3D stack middle.21 + + Sheet.22 + + + + Sheet.23 + + + + + 3D stack middle.24 + + Sheet.25 + + + + Sheet.26 + + + + + Sheet.27 + HBIOS Proxy (RST 08) + + HBIOS Proxy (RST 08) + + Sheet.28 + Application Area (TPA) + + Application Area (TPA) + + Sheet.29 + Operating System CP/M or ZSYS + + Operating System CP/M or ZSYS + + Sheet.30 + CBIOS + + CBIOS + + Sheet.31 + BDOS + + BDOS + + Sheet.32 + CCP + + CCP + + Data block.33 + + Sheet.34 + + + + Sheet.35 + + + + Sheet.36 + + + + + Sheet.37 + + + + Sheet.38 + HBIOS (Hardware Drivers) + + HBIOS (Hardware Drivers) + + Sheet.39 + + + + Sheet.40 + + + + Sheet.43 + Z80 CPU Address Space + + Z80 CPU Address Space + + Sheet.41 + Banked Lower 32K + + Banked Lower 32K + + Sheet.42 + Fixed Upper 32K + + Fixed Upper 32K + + Sheet.1 + $10000 + + + $10000 + + Sheet.4 + $0000 + + + $0000 + + Bracket + + + + Sheet.45 + Bank 0 + + Bank 0 + + Sheet.47 + App/OS Banks + + App/OS Banks + + Sheet.48 + Bank N-1 + + Bank N-1 + + Sheet.49 + Bank N + + Bank N + + Sheet.50 + • • • + + • • • + + Bracket.51 + + + + Sheet.55 + + + + Sheet.56 + Physical RAM (32K per bank) + + Physical RAM (32K per bank) + + Bracket.57 + ` + + + ` + + Sheet.58 + + + + 3D stack top + RAM Disk + + Sheet.61 + + + + Sheet.62 + + + + Sheet.63 + + + + RAM Disk + + + Pointer (1-D) + + + + Pointer (1-D).65 + + + + Pointer (1-D).66 + + + + Pointer (1-D).67 + + + + Sheet.70 + + + + Sheet.68 + HBIOS Function Call w/ Bank Switch + + HBIOS Function Call w/ Bank Switch + + Sheet.69 + RomWBW Bank Switched Memory Layout + + RomWBW Bank Switched Memory Layout + + Sheet.59 + + + + Sheet.52 + Fixed Mapping of Upper 32K to Last Bank + + Fixed Mapping of Upper 32K to Last Bank + + Sheet.72 + + + + Sheet.74 + + + + diff --git a/UserGuide/Graphics/CharacterEmulationVideoServices.svg b/UserGuide/Graphics/CharacterEmulationVideoServices.svg new file mode 100644 index 00000000..6632a956 --- /dev/null +++ b/UserGuide/Graphics/CharacterEmulationVideoServices.svg @@ -0,0 +1,830 @@ + + + + + + + + + + + + + + + + Page-1 + + Sheet.81 + + + + Sheet.80 + + + + Sheet.1 + Character I/O Services + + Character I/O Services + + Sheet.2 + + + + Sheet.8 + + + + Sheet.9 + Emulation Services + + Emulation Services + + Sheet.10 + TTY + + TTY + + Sheet.11 + ANSI + + ANSI + + Sheet.12 + + + + Sheet.13 + + + + Sheet.14 + Video Display Adapter Services + + Video Display Adapter Services + + Sheet.18 + + + + Sheet.27 + UART + + UART + + Sheet.34 + ASCI + + ASCI + + Terminal.20 + + Sheet.36 + + + + Sheet.37 + + + + Sheet.38 + + + + Sheet.39 + + + + + Sheet.40 + CVDU + + CVDU + + Sheet.41 + + + + Sheet.47 + UPD7220 + + UPD7220 + + Sheet.54 + N8 + + N8 + + Sheet.56 + CIOXXX + + CIOXXX + + Sheet.57 + VDAXXX + + VDAXXX + + Sheet.58 + Operating System / Utilities + + Operating System / Utilities + + Sheet.59 + Others... + + Others... + + Sheet.60 + + + + Sheet.61 + + + + Sheet.62 + EMUXXX + + EMUXXX + + Sheet.15 + + + + Terminal.16 + + Sheet.42 + + + + Sheet.43 + + + + Sheet.44 + + + + Sheet.45 + + + + + Sheet.46 + + + + Terminal.48 + + Sheet.49 + + + + Sheet.50 + + + + Sheet.51 + + + + Sheet.52 + + + + + Sheet.53 + + + + Terminal.22 + + Sheet.23 + + + + Sheet.24 + + + + Sheet.25 + + + + Sheet.26 + + + + + Sheet.28 + + + + Terminal.29 + + Sheet.30 + + + + Sheet.31 + + + + Sheet.32 + + + + Sheet.33 + + + + + Sheet.35 + + + + Sheet.55 + RS-232 + + RS-232 + + Sheet.63 + RS-232 + + RS-232 + + Sheet.64 + VGA + + VGA + + Sheet.65 + VGA + + VGA + + Sheet.66 + NTSC + + NTSC + + Sheet.67 + UART + + UART + + Sheet.68 + ASCI + + ASCI + + Sheet.69 + VDU + + VDU + + Sheet.74 + SY6545 + + SY6545 + + Sheet.75 + MC8563 + + MC8563 + + Sheet.76 + uPD7220 + + uPD7220 + + Sheet.79 + Character / Emulation / Video Services + + Character / Emulation / Video Services + + Sheet.82 + HBIOS + + HBIOS + + Sheet.83 + HARDWARE + + HARDWARE + + Sheet.84 + TMS9918 + + TMS9918 + + Terminal.87 + + Sheet.88 + + + + Sheet.89 + + + + Sheet.90 + + + + Sheet.91 + + + + + Sheet.92 + VDU + + VDU + + Sheet.93 + + + + Sheet.94 + NTSC + + NTSC + + Sheet.96 + + + + Sheet.7 + + + + Sheet.17 + + + + Sheet.3 + + + + Sheet.4 + + + + diff --git a/UserGuide/Graphics/Logo.svg b/UserGuide/Graphics/Logo.svg new file mode 100644 index 00000000..586d6f1f --- /dev/null +++ b/UserGuide/Graphics/Logo.svg @@ -0,0 +1,62 @@ + + + + + + + + Page-1 + + Sheet.34 + + + + Sheet.35 + + + + Sheet.36 + + + + Sheet.38 + + + + Sheet.39 + + + + Sheet.44 + + + + Sheet.48 + + + + Sheet.49 + + + + Sheet.50 + + + + Sheet.52 + + + + Sheet.53 + + + + diff --git a/UserGuide/Graphics/Panel.svg b/UserGuide/Graphics/Panel.svg new file mode 100644 index 00000000..ca83e5d7 --- /dev/null +++ b/UserGuide/Graphics/Panel.svg @@ -0,0 +1,369 @@ + + + + + + + + Page-1 + + Sheet.1 + + + + Sheet.2 + + + + Sheet.3 + + + + Sheet.8 + + + + Sheet.9 + + + + Sheet.10 + + + + Sheet.11 + + + + Sheet.12 + + + + Sheet.13 + + + + Sheet.14 + + + + Sheet.18 + + + + Sheet.19 + + + + Sheet.20 + + + + Sheet.21 + + + + Sheet.22 + + + + Sheet.23 + + + + Sheet.24 + + + + Sheet.25 + + + + Sheet.26 + + + + Sheet.27 + + + + Sheet.28 + + + + Sheet.29 + + + + Sheet.30 + + + + Sheet.31 + + + + Sheet.32 + + + + Sheet.33 + + + + Sheet.34 + + + + Sheet.35 + 8 + + 8 + + Sheet.36 + 4 + + 4 + + Sheet.37 + 2 + + 2 + + Sheet.38 + 1 + + 1 + + Sheet.39 + High + + High + + Sheet.40 + + + + Sheet.41 + + + + Sheet.42 + + + + Sheet.43 + 8 + + 8 + + Sheet.44 + 4 + + 4 + + Sheet.45 + 2 + + 2 + + Sheet.46 + 1 + + 1 + + Sheet.47 + Low + + Low + + Sheet.48 + 7 + + 7 + + Sheet.49 + 6 + + 6 + + Sheet.50 + 5 + + 5 + + Sheet.52 + 4 + + 4 + + Sheet.53 + 3 + + 3 + + Sheet.54 + 2 + + 2 + + Sheet.55 + 1 + + 1 + + Sheet.56 + 0 + + 0 + + Sheet.57 + + + + Sheet.58 + Auto + + Auto + + Sheet.59 + Menu + + Menu + + Sheet.61 + + + + Sheet.62 + CRT + + CRT + + Sheet.63 + Serial + + Serial + + Sheet.64 + + + + Sheet.65 + Sec + + Sec + + Sheet.66 + Pri + + Pri + + Sheet.67 + + + + Sheet.68 + Disk + + Disk + + Sheet.69 + ROM + + ROM + + Sheet.70 + + + + Sheet.71 + Floppy + + Floppy + + Sheet.72 + Hard + + Hard + + Sheet.73 + + + + Sheet.74 + 4 + + 4 + + Sheet.75 + 2 + + 2 + + Sheet.76 + 1 + + 1 + + Sheet.78 + ROM App / Boot Slice + + ROM App / Boot Slice + + Sheet.79 + ROM Apps: 0=Monitor 1=BASIC 2=Forth 3=Game 4=CP/M 2.2 5=Z-Sys... + + ROM Apps: 0=Monitor 1=BASIC 2=Forth 3=Game 4=CP/M 2.2 5=Z-System 6=Net Boot 7=User + + Sheet.80 + + + + Sheet.81 + + + + Sheet.82 + + + + Sheet.84 + Console + + Console + + Sheet.85 + + + + Sheet.86 + + + + Sheet.87 + + + + Sheet.88 + Boot + + Boot + + diff --git a/UserGuide/Graphics/hd1k.svg b/UserGuide/Graphics/hd1k.svg new file mode 100644 index 00000000..2581bfe1 --- /dev/null +++ b/UserGuide/Graphics/hd1k.svg @@ -0,0 +1,1088 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Page-1 + + + + Sheet.95 + 0 + + + + 0 + + Sheet.101 + 1 + + + + 1 + + Sheet.102 + 2 + + + + 2 + + Sheet.103 + 3 + + + + 3 + + Sheet.105 + . . . + + + + . . . + + Sheet.104 + N + + + + N + + Sheet.201 + + + + Sheet.69 + RomWBW Hard Disk Anatomy (Modern / hd1k) + + + + RomWBW Hard Disk Anatomy (Modern / hd1k) + + Sheet.106 + RomWBW Hard Disk (IDE/ATA/ATAPI/CF/SD/USB) + + + + RomWBW Hard Disk (IDE/ATA/ATAPI/CF/SD/USB) + + Sheet.107 + FAT Partition + + + + FAT Partition + + Sheet.119 + Sector 0 + + + + Sector 0 + + Sheet.120 + + + + Sheet.121 + + + + Sheet.122 + Type 2E + + + + Type 2E + + Sheet.123 + Type 06 + + + + Type 06 + + Sheet.124 + + + + Sheet.125 + + + + Sheet.126 + Partition Table + + + + Partition Table + + Sheet.131 + + + + Bracket.132 + + + + + + + Sheet.135 + + + + Sheet.139 + CP/M System Area (16 KB) + + + + CP/M System Area (16 KB) + + Sheet.141 + + + + Sheet.142 + + + + Sheet.143 + + + + Sheet.144 + + + + Sheet.165 + + + + Sheet.166 + + + + Sheet.167 + + + + Sheet.168 + + + + Stack pointer.179 + + + + + + + Sheet.202 + RomWBW Partition (8MB * N) + + + + RomWBW Partition (8MB * N) + + Sheet.205 + Prefix (1 MB typical) + + + + Prefix (1 MB typical) + + Dynamic connector + + + + Dynamic connector.207 + + + + Sheet.118 + MBR + + + + MBR + + Sheet.208 + + + + Sheet.128 + Slice (8 MB) + + + + Slice (8 MB) + + Bracket.146 + + + + + + + Sheet.581 + + + + Sheet.582 + CP/M File System (8,176 KB) + + + + CP/M File System (8,176 KB) + + Sheet.583 + + + + Sheet.590 + + + + Bracket.301 + + + + + + + Bracket.592 + + + + + + + diff --git a/UserGuide/Graphics/hd512.svg b/UserGuide/Graphics/hd512.svg new file mode 100644 index 00000000..c4cfa578 --- /dev/null +++ b/UserGuide/Graphics/hd512.svg @@ -0,0 +1,236 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Page-1 + + Sheet.69 + RomWBW Hard Disk Anatomy (Classic / hd512) + + RomWBW Hard Disk Anatomy (Classic / hd512) + + Sheet.259 + 0 + + 0 + + Sheet.260 + 1 + + 1 + + Sheet.261 + 2 + + 2 + + Sheet.262 + 3 + + 3 + + Sheet.263 + . . . + + . . . + + Sheet.264 + N + + N + + Sheet.265 + + + + Sheet.266 + RomWBW Hard Disk (IDE/ATA/ATAPI/CF/SD/USB) + + RomWBW Hard Disk (IDE/ATA/ATAPI/CF/SD/USB) + + Sheet.267 + FAT Partition + + FAT Partition + + Sheet.268 + Sector 0 + + Sector 0 + + Sheet.269 + + + + Sheet.270 + + + + Sheet.271 + Type 06 + + Type 06 + + Sheet.272 + + + + Sheet.273 + + + + Sheet.274 + + + + Sheet.275 + Partition Table + + Partition Table + + Sheet.276 + + + + Bracket.132 + + + + Sheet.278 + + + + Sheet.279 + CP/M System Area (128 KB) + + CP/M System Area (128 KB) + + Sheet.280 + + + + Sheet.281 + + + + Sheet.282 + + + + Sheet.283 + + + + Sheet.284 + + + + Sheet.285 + + + + Sheet.286 + + + + Sheet.287 + + + + Stack pointer.179 + + + + Sheet.289 + RomWBW Data (8,320 KB * N) + + RomWBW Data (8,320 KB * N) + + Dynamic connector.207 + + + + Sheet.294 + MBR + + MBR + + Sheet.295 + + + + Sheet.296 + Slice (8,320 KB) + + Slice (8,320 KB) + + Sheet.298 + + + + Sheet.299 + CP/M File System (8 MB) + + CP/M File System (8 MB) + + Sheet.300 + + + + Bracket.301 + + + + Bracket.302 + + + + diff --git a/UserGuide/index.html b/UserGuide/index.html new file mode 100644 index 00000000..a7a4842c --- /dev/null +++ b/UserGuide/index.html @@ -0,0 +1,5204 @@ + + + + + + + + + + + User Guide - RomWBW Documentation V3.6 + + + + + + + + + + + + + + + + +
+
+
+
+ +

RomWBW User Guide \ +Version 3.6 \ +Wayne Warthen (wwarthen@gmail.com) \ +30 May 2025

+

Preface

+

This document is a general usage guide for the RomWBW software and is +generally the best place to start with RomWBW.

+

On a personal note, I found this document very difficult to write. +Members of the retro-computing community have dramatically different +experiences, skill levels, and desires. I realize some readers will find +this document far too basic. Others will find it lacking in many areas. +I am doing my best and encourage you to provide constructive feedback.

+

Conventions Used

+
Size Suffixes
+

Within the documentation and in RomWBW in general, the use of size +suffixes KB, MB, GB, and TB refer to the binary variant as shown below. +The modern suffixes (KiB, MiB, etc.) are not used here because they were +not prevalent during the time that the RomWBW OSes were used. This keeps +all of RomWBW and associated applications consistent.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SuffixValueMeaning
KB10241,024 bytes
MB102421,048,576 bytes
GB102431,073,741,824 bytes
TB102441,099,511,627,776 bytes
+ +

Many of the references in the documentation to Internet addresses (URLs) +do not provide the address in the text. However, these links are +embedded and “clickable” within the documents. Your PDF viewer should +highlight these links in some manner (typically an alternate color or an +underline).

+

Getting Started

+

Installation

+

In general, installation of RomWBW on your platform is very simple. You +just need to program your ROM with the correct ROM image from the RomWBW +distribution. Subsequently, you can write disk images on your disk +drives (IDE disk, CF Card, SD Card, etc.) which then provides even more +functionality.

+

Depending on how you got your hardware, you may have already been +provided with a pre-programmed ROM chip. If so, use that initially. +Otherwise, you will need to use a ROM programmer to initially program +your ROM chip. Please refer to the documentation that came with your ROM +programmer for more information.

+

The fully-built distribution releases are available on the RomWBW +Releases Page +(https://github.com/wwarthen/RomWBW/releases) of the repository.

+

The distribution is a .zip archive. After downloading it to a working +directory on your modern computer (Windows/Linux/Mac) use any zip tool +to extract the contents of the archive.

+

The Binary directory of the distribution contains the pre-built ROM +images.
+Refer to RomWBW +Hardware +to identify the correct ROM image for your system.

+

A complete list of the currently supported platforms is found in RomWBW +Hardware. +You must burn the correct ROM image that matches your hardware

+

Once you have a running RomWBW system, you can generally update your ROM +to a newer version in-situ with the included ROM Flashing tool (Will +Sowerbutts’ FLASH application) as described in the +Upgrading chapter of this document.

+

System Startup

+

Initially, don’t worry about trying to write a disk image to any disk +(or CF/SD/USB) devices you have. This will be covered later. You will be +able to boot and check out your system with just the ROM.

+

Connect a serial terminal or computer with terminal emulation software +to the primary serial port of your CPU board. You may need to refer to +your hardware provider’s documentation for details. A null-modem +connection may be required. Set the baud rate as indicated in RomWBW +Hardware. +Set the line characteristics to 8 data bits, 1 stop bit, no parity, and +no flow control. If possible, select ANSI or VT-100 terminal emulation. +Hardware flow control is not required for terminal operation, but may be +necessary for Serial Port Transfers.

+

RomWBW will automatically attempt to detect and support typical add-on +components for each of the systems supported. More information on the +required system configuration and optional supported components for each +ROM is found in RomWBW +Hardware +.

+

Upon power-up, your terminal should display a sign-on banner within 2 +seconds followed by hardware inventory and discovery information. When +hardware initialization is completed, a boot loader prompt allows you to +choose a ROM-based operating system, system monitor, application, or +boot from a disk device.

+

Core System Information

+

During startup, the first few lines of information displayed provide the +most basic information on your system. In the example above, these lines +are the Core System Information:

+
RomWBW HBIOS v3.5, 2025-03-01
+
+RCBus [RCZ80_kio] Z80 @ 7.372MHz
+0 MEM W/S, 1 I/O W/S, INT MODE 2, Z2 MMU
+512KB ROM, 512KB RAM
+ROM VERIFY: 00 00 00 00 PASS
+
+

The first line is a version identification banner for RomWBW. After that +you see a group of 4 lines describing the basic system. In this example, +the platform is the RCBus running a configuration named “RCZ80_kio”. The +CPU is a Z80 with a current clock speed of 7.372 MHz. There are 0 memory +wait states and 1 I/O wait state. Z80 interrupt mode 2 is active and the +bank memory manager is type “Z2” which is standard for RCBus. The system +has 512KB of ROM total and 512KB of RAM total. Finally, a verification +of the checksums of the critical ROM banks is shown (all 4 should be +00).

+

RomWBW attempts to detect the running configuration of the system at +startup. Depending on your hardware, there may be inaccuracies in this +section. For example, in some cases the CPU clock speed is assumed +rather than actually measured. This does not generally affect the +operation of your system. If you want to correct any of the information +displayed, you can create a custom ROM which is described later.

+

Hardware Discovery

+

The next set of messages during boot show the hardware devices as they +are probed and initially configured. In the example above, these lines +are:

+
KIO: IO=0x80 ENABLED
+CTC: IO=0x84 TIMER MODE=TIM16
+AY: MODE=RCZ80 IO=0xD8 NOT PRESENT
+SIO0: IO=0x89 SIO MODE=115200,8,N,1
+SIO1: IO=0x8B SIO MODE=115200,8,N,1
+DSRTC: MODE=STD IO=0xC0 NOT PRESENT
+MD: UNITS=2 ROMDISK=384KB RAMDISK=256KB
+FD: MODE=RCWDC IO=0x50 NOT PRESENT
+IDE: IO=0x10 MODE=RC
+IDE0: NO MEDIA
+IDE1: NO MEDIA
+PPIDE: IO=0x20
+PPIDE0: LBA BLOCKS=0x00773800 SIZE=3815MB
+PPIDE1: NO MEDIA
+
+

What you see will depend on your specific system and ROM, but should +match the hardware present in your system. Each device has a tag that +precedes the colon. This tag identifies the driver and instance of each +device. For example, the tag “SIO0:” refers to the SIO serial port +driver and specifically the first channel. The “SIO1:” tag refers to the +second channel.

+

In many cases you will see IO=0xNN in the data following the tag. This +identifies the base I/O port address of the hardware device and is +useful for identifying hardware conflicts.

+

Note that you may see some lines indicating that the associated hardware +is not present. Above, you can see that the FD driver did not find a +floppy interface. Lines such as these are completely normal when your +system does not have the associated hardware.

+

Finally, be aware that all ROMs are configured to identify specific +hardware devices at specific port addresses. If you add hardware to your +system that is not automatically identified, you may need to build a +custom ROM to add support for it. Building a custom ROM is covered +later.

+

RomWBW +Hardware +contains a list of the RomWBW hardware devices which may help you +identify the hardware discovered in your system.

+

Device Unit Assignments

+

In order to support a wide variety of hardware, RomWBW HBIOS uses a +modular approach to implementing device drivers and presenting devices +to an operating system. In general, all devices are classified as one of +the following:

+
    +
  • Disk (RAM/ROM Disk, Floppy Disk, Hard Disk, CF Card, SD Card, etc.)
  • +
  • Character (Serial Ports, Parallel Ports, etc.)
  • +
  • Video (Video Display/Keyboard Interfaces)
  • +
  • Sound (Audio Playback Devices)
  • +
  • RTC/NVRAM (Real Time Clock, Non-volatile RAM)
  • +
  • System (Internal Services, e.g. Timer, DMA, etc.)
  • +
+

HBIOS uses the concept of unit numbers to present a generic set of +hardware devices to the operating system. As an example, a typical +system might have a ROM Disk, RAM Disk, Floppy Drives, and Disk Drives. +All of these are considered disk devices and are presented to the +operating system as generic block devices. This means that each +operating system does not need to embed code to interact directly with +all of the different hardware devices – RomWBW takes care of that.

+

In the final group of startup messages, a device unit summary table is +displayed so that you can see how the actual hardware devices have been +mapped to unit numbers during startup.

+
Unit        Device      Type              Capacity/Mode
+----------  ----------  ----------------  --------------------
+Char 0      UART0:      RS-232            38400,8,N,1
+Char 1      UART1:      RS-232            38400,8,N,1
+Disk 0      MD1:        RAM Disk          384KB,LBA
+Disk 1      MD0:        ROM Disk          384KB,LBA
+Disk 2      FD0:        Floppy Disk       3.5",DS/HD,CHS
+Disk 3      FD1:        Floppy Disk       3.5",DS/HD,CHS
+Disk 4      IDE0:       CompactFlash      3815MB,LBA
+Disk 5      IDE1:       Hard Disk         --
+Disk 6      PRPSD0:     SD Card           1886MB,LBA
+Video 0     CVDU0:      CRT               Text,80x25
+
+

In this example, you can see that the system has a total of 7 Disk Units +numbered 0-6. There are also 2 Character Units and 1 Video Unit. The +table shows the unit numbers assigned to each of the devices. Notice how +the unit numbers are assigned sequentially regardless of the specific +device.

+

There may or may not be media in the disk devices listed. For example, +the floppy disk devices (Disk Units 2 & 3) may not have a floppy in the +drive. Also note that Disk Unit 4 shows a disk capacity, but Disk Unit 5 +does not. This is because the PPIDE interface of the system supports up +to two drives, but there is only one actual drive attached. A unit +number is assigned to all available devices regardless of whether they +have actual media installed at boot time.

+

Note that Character Unit 0 is the initial system console unless modified +in a customized ROM image.

+

If your system has an RTC/NVRAM device, it will not be listed in the +unit summary table. Since only a single RTC/NVRAM device can exist in +one system, unit numbers are not required nor used for this type of +device. Also, System devices are not listed because they are entirely +internal to RomWBW.

+

Startup Example

+

Here is an example of a fairly typical startup. Your system will have +different devices and configuration, but the startup should look +similar.

+
RomWBW HBIOS v3.5, 2025-03-01
+
+RCBus [RCZ80_kio] Z80 @ 7.372MHz
+0 MEM W/S, 1 I/O W/S, INT MODE 2, Z2 MMU
+512KB ROM, 512KB RAM
+ROM VERIFY: 00 00 00 00 PASS
+
+KIO: IO=0x80 ENABLED
+CTC: IO=0x84 TIMER MODE=TIM16
+AY: MODE=RCZ80 IO=0xD8 NOT PRESENT
+SIO0: IO=0x89 SIO MODE=115200,8,N,1
+SIO1: IO=0x8B SIO MODE=115200,8,N,1
+DSRTC: MODE=STD IO=0xC0 NOT PRESENT
+MD: UNITS=2 ROMDISK=384KB RAMDISK=256KB
+FD: MODE=RCWDC IO=0x50 NOT PRESENT
+IDE: IO=0x10 MODE=RC
+IDE0: NO MEDIA
+IDE1: NO MEDIA
+PPIDE: IO=0x20
+PPIDE0: LBA BLOCKS=0x00773800 SIZE=3815MB
+PPIDE1: NO MEDIA
+
+Unit        Device      Type              Capacity/Mode
+----------  ----------  ----------------  --------------------
+Char 0      SIO0:       RS-232            115200,8,N,1
+Char 1      SIO1:       RS-232            115200,8,N,1
+Disk 0      MD0:        RAM Disk          256KB,LBA
+Disk 1      MD1:        ROM Disk          384KB,LBA
+Disk 2      IDE0:       Hard Disk         --
+Disk 3      IDE1:       Hard Disk         --
+Disk 4      PPIDE0:     CompactFlash      3815MB,LBA
+Disk 5      PPIDE1:     Hard Disk         --
+
+

If your system completes the ROM-based boot process successfully, you +should see the RomWBW Boot Loader prompt. For example:

+
RCBus [RCZ80_kio] Boot Loader
+
+Boot [H=Help]:
+
+

If you get to this prompt, your system has completed the boot process +and is ready to accept commands. Note that the Boot Loader is not an +operating system or application. It is essentially the point where you +choose which operating system or application you want RomWBW to execute.

+

The Boot Loader is explained in detail in the next section. For now, you +can try a few simple commands to confirm that you can interact with the +system.

+

At the Boot Loader prompt, you can type H <enter> for help. You can +type L <enter> to list the available built-in ROM applications. If +your terminal supports ANSI escape sequences, you can try the ‘P’ +command to play a simple on-screen game. Instructions for the game are +found in RomWBW +Applications.

+

If all of this seems fine, your ROM has been successfully programmed.

+

Boot Loader Operation

+

Once your system has completed the startup process, it presents a Boot +Loader command prompt. The purpose of the Boot Loader is to select and +launch a desired application or operating system. It also has the +ability to configure some aspects of system operation.

+

After starting your system, following the hardware initialization, you +will see the RomWBW Boot Loader prompt. Below is an example. Note that +the text preceding “Boot Loader” will vary and identifies your specific +system and configuration.

+
Mark IV [MK4_wbw] Boot Loader
+
+Boot [H=Help]:
+
+

From the Boot Loader prompt, you can enter commands to select and launch +any of the RomWBW operating systems or ROM applications. It also allows +you to manage some basic settings of the system. To enter a command, +just enter the command followed by \<enter>.

+

For example, typing H<enter> will display a short command summary:

+
Boot [H=Help]: h
+
+  L           - List ROM Applications
+  D           - Device Inventory
+  R           - Reboot System
+  W           - RomWBW Configure
+  I <u> [<c>] - Set Console Interface/Baud Rate
+  V [<n>]     - View/Set HBIOS Diagnostic Verbosity
+  <u>[.<s>]   - Boot Disk Unit/Slice
+
+

Likewise the L command (List ROM Applications) will display the list +of ROM Applications that you can launch right from the Boot Loader:

+
Boot [H=Help]: L
+
+ROM Applications:
+
+  M: Monitor
+  Z: Z-System
+  C: CP/M 2.2
+  F: Forth
+  B: BASIC
+  T: Tasty BASIC
+  P: Play a Game
+  N: Network Boot
+  X: XModem Flash Updater
+  U: User App
+
+

A more complete description of these options is found below in System +Management.

+

Starting Applications from ROM

+

To start a ROM application you just enter the corresponding letter at +the Boot Loader prompt. In the following example, we launch the built-in +Microsoft BASIC interpreter. From within BASIC, we use the BYE command +to return to the Boot Loader:

+
Boot [H=Help]: b
+
+Loading BASIC...
+Memory top?
+Z80 BASIC Ver 4.7b
+Copyright (C) 1978 by Microsoft
+55603 Bytes free
+Ok
+bye
+
+
+Mark IV [MK4_wbw] Boot Loader
+
+Boot [H=Help]:
+
+

The following ROM applications and OSes are available at the boot loader +prompt:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ApplicationDescription
MonitorZ80 system debug monitor w/ Intel Hex loader
CP/M 2.2Digital Research CP/M 2.2 OS
Z-SystemZSDOS 1.1 w/ ZCPR 1 (Enhanced CP/M compatible OS)
ForthBrad Rodriguez’s ANSI compatible Forth language
BASICMicrosoft ROM BASIC
Tasty BASICDimitri Theuling’s Tiny BASIC implementation
PlayA simple video game (requires ANSI terminal emulation)
Network BootBoot system via Wiznet MT011 device
Flash UpdateUpload and flash a new ROMWBW image using xmodem
User AppUser written application placeholder
+

The User App is provided as a way to access a custom written ROM module. +In the pre-built ROMs, selecting User App will just return to the Boot +Loader menu. If you are interested in creating a custom application to +run here, review the “usrrom.asm” file in the Source/HBIOS folder of the +distribution.

+

Each of the ROM Applications is documented in RomWBW +Applications. +Some of the applications (such as BASIC) also have their own independent +manual in the Doc directory of the distribution. The OSes included in +the ROM (CP/M 2.2 & Z-System) are described in the Operating Systems +chapter of this document.

+

In general, the command to exit any of these applications and restart +the system is BYE. The exceptions are the Monitor which uses X and +Play which uses Q.

+

NOTE: Of the ROM Applications, only the operating systems (CP/M and +Z-System) have the ability to interact with disk drives. So, other than +these 2 OSes, the ROM Applications do not have any way to save or +load data from peristent/disk storage. For example, if you launch BASIC +from the Boot Loader, you will not be able to save or load your +programs. You will need to start an operating system first and then run +BASIC in order to save or load programs.

+

Two of the ROM Applications are, in fact, complete operating systems. +Specifically, “CP/M 2.2” and “Z-System” are provided so that you can +actually start either operating system directly from your ROM. This +technique is useful when:

+
    +
  • You don’t yet have any real disk drives in your system
  • +
  • You want to setup real disk drives for the first time
  • +
  • You are upgrading your system and need to upgrade your real disk + drives
  • +
+

The RAM disk and ROM disk drives will be available even if you have no +physical disk devices attached to your system.

+

Booting an operating system from ROM is not intended as a way to use +your operating system on a long-term basis. The ROM disk has only a +small subset of the operating system files. Additionally, you cannot +easily customize your ROM disk because you cannot write to it. For any +significant use of an operating system, you should boot directly to the +disk/slice that contains the complete operating system. This is +described in the next section.

+

Starting Operating Systems from Disk

+

In order to make use of the more sophisticated operating systems +available with RomWBW, you will need to boot an operating system from a +disk. Setting up disks is described in detail later. For now, we will +just go over the command line for performing this type of boot.

+

From the Boot Loader prompt, you can enter a number (\<diskunit>) +and optionally a dot followed by a second number (\<slice>). The +\<disk unit> unit number refers to a disk unit that was displayed +when the system was booted – essentially it specifies the specific +physical disk drive you want to boot. The \<slice> numbers refers +to a portion of the disk unit to boot. If no slice is specified, then it +is equivalent to booting from the first slice (slice 0). Disk units and +slices are described in more detail later.

+

Following this, you should see the operating system startup messages. +Your operating system prompt will typically be A> and when you look at +the drive letter assignments, you should see that A: has been assigned +to the disk and slice you selected to boot.

+

If you receive the error message “Disk not bootable!”, you have either +failed to properly initialize the disk and slice requested or you have +selected an invalid/unavailable disk/slice.

+

The following example shows a disk boot into the first slice of disk +unit 4 which happens to be the CP/M 2.2 operating system on this disk. +This is accomplished by entering just the number ‘4’ and pressing +\<enter>.

+
Boot [H=Help]: 4
+
+Booting Disk Unit 4, Slice 0, Sector 0x00000800...
+
+Volume "Unlabelled" [0xD000-0xFE00, entry @ 0xE600]...
+
+CBIOS v3.1.1-pre.194 [WBW]
+
+Formatting RAMDISK...
+
+Configuring Drives...
+
+        A:=IDE0:0
+        B:=MD0:0
+        C:=MD1:0
+        D:=FD0:0
+        E:=FD1:0
+        F:=IDE0:1
+        G:=IDE0:2
+        H:=IDE0:3
+        I:=PRPSD0:0
+        J:=PRPSD0:1
+        K:=PRPSD0:2
+        L:=PRPSD0:3
+
+        1081 Disk Buffer Bytes Free
+
+CP/M-80 v2.2, 54.0K TPA
+
+A>
+
+

Notice that a list of drive letters and their assignments to RomWBW +devices and slices is displayed during the initialization of the +operating system.

+

Here is another example where we are booting disk unit 4, slice 3 which +is the CP/M 3 operating system on this disk:

+
Boot [H=Help]: 4.3
+
+Booting Disk Unit 4, Slice 3, Sector 0x0000C800...
+
+Volume "Unlabelled" [0x0100-0x1000, entry @ 0x0100]...
+
+CP/M V3.0 Loader
+Copyright (C) 1998, Caldera Inc.
+
+ BNKBIOS3 SPR  F600  0800
+ BNKBIOS3 SPR  4500  3B00
+ RESBDOS3 SPR  F000  0600
+ BNKBDOS3 SPR  1700  2E00
+
+ 60K TPA
+
+CP/M v3.0 [BANKED] for HBIOS v3.5
+
+A>
+
+

Some operating systems (such as CP/M 3 shown above) do not list the +drive assignments during initialization. In this case, you can use the +ASSIGN command to display the current assignments.

+

The Boot Loader simply launches whatever is in the disk unit/slice you +have specified. It does not know what operating system is at that +location. The layout of operating systems on disk media is described in +the Disk Images section of this document.

+

Auto-Submit Batch Files

+

All of the operating systems supplied with RomWBW have the ability to +execute a “batch” of commands by creating a batch submission file +containing the commands to be executed. The mechanism for running +commands automatically at startup varies by operating system. In some +cases, it was built into the original operating system. In other cases, +I have added this capability in the RomWBW BIOS of the operating system.

+

In all cases, the file containing the commands to run at startup must be +on the boot drive (A:). RomWBW automatically assigns A: to the disk +slice you choose to boot. Adding a startup command file to the ROM Disk +is not recommended because it would require customizing and building a +new ROM. Use of bootable disk slices is preferred since the startup +command files can be added/edited without any special system +customization.

+

Here is an overview for each operating system:

+
    +
  • +

    CP/M 2.2 - Will run PROFILE.SUB as a SUBMIT file if it exists in + A: at startup. Note that original CP/M 2.2 itself did not have this + ability – it was added to the RomWBW CP/M 2.2 BIOS. The use of SUBMIT + files is documented in Section 1.6.7 SUBMIT Command of the CPM Manual + included in the Doc/CPM folder of the RomWBW distribution.

    +
  • +
  • +

    Z-System (ZSDOS 1.1) - Will run run PROFILE.SUB as a SUBMIT file + if it exists in A: at startup. Works exactly the same as CP/M 2.2. The + original Z-System ZSDOS 1.1 did not have this ability – it was added + to the RomWBW Z-System BIOS. The Z-System documentation does not cover + the use of SUBMIT files – please refer to the CP/M 2.2 documentation.

    +
  • +
  • +

    NZCOM - Will run the command STARTZCM at startup. This is normally + an alias file, which you can edit using SALIAS. Please see Section 3.1 + Creating an Alias of the NZCOM Users Manual included in the Doc/CPM + folder of the RomWBW distribution. Do not modify this file unless you + fully understand the NZCOM boot process. Note that NZCOM itself is + launched from ZSDOS via the included PROFILE.SUB file.

    +
  • +
  • +

    CP/M 3 - Will run PROFILE.SUB as a SUBMIT file if it exists in A: + at startup. This mechanism is built into the CP/M 3 operating + system.
    + Please see Section 4.5 Executing Multiple Commands and Section 5.2.74 + Executing the SUBMIT Command of the CPM3 Users Guide included in the + Doc/CPM folder of the RomWBW distribution.

    +
  • +
  • +

    Z3PLUS - Will run the command STARTZ3P at startup. This is + normally an alias file, which you can edit using SALIAS. Please see + Section 3.1 Creating an Alias of the Z3PLUS Users Manual included in + the Doc/CPM folder of the RomWBW distribution. Do not modify this file + unless you fully understand the Z3PLUS boot process. Note that Z3PLUS + itself is launched from CP/M 3 via the included PROFILE.SUB file.

    +
  • +
  • +

    ZPM3 - Will run the command STARTZPM at startup. This is normally + an alias file. You use SALIAS to edit such files. ZPM3 has no real + documentation. The NZCOM documentation of STARTZCM is generally + correct for ZPM3.

    +
  • +
+

Since RomWBW can utilize many disk slices, it is very easy to create +slices for specific workflows (editing, software development, games, +etc.). You can then just boot to the slice that is optimized for the +task you want to perform. Each such slice may have its own startup +command batch file that customizes the environment for the specific +workflow desired.

+

System Management

+

Listing Device Inventory

+

The device units available in your system are listed in the boot +messages. However, if that list has scrolled off of your screen, you can +use the ‘D’ command to display a list of them at any time from the Boot +Loader prompt.

+
Unit        Device      Type              Capacity/Mode
+----------  ----------  ----------------  --------------------
+Char 0      ASCI0:      RS-232            38400,8,N,1
+Char 1      ASCI1:      RS-232            38400,8,N,1
+Char 2      UART0:      RS-232            38400,8,N,1
+Char 3      UART1:      RS-232            38400,8,N,1
+Char 4      UART2:      RS-232            38400,8,N,1
+Char 5      UART3:      RS-232            38400,8,N,1
+Char 6      TERM0:      Terminal          Video 0,ANSI
+Char 7      PRPCON0:    Terminal          Term Module,ANSI
+Disk 0      MD0:        RAM Disk          352KB,LBA
+Disk 1      MD1:        Flash Drive       384KB,LBA
+Disk 2      FD0:        Floppy Disk       3.5",DS/HD,CHS
+Disk 3      FD1:        Floppy Disk       3.5",DS/HD,CHS
+Disk 4      IDE0:       CompactFlash      3815MB,LBA
+Disk 5      IDE1:       Hard Disk         --
+Disk 6      IDE2:       CompactFlash      3823MB,LBA
+Disk 7      IDE3:       Hard Disk         --
+Disk 8      IDE4:       Hard Disk         --
+Disk 9      IDE5:       Hard Disk         --
+Disk 10     SD0:        SD Card           --
+Disk 11     PRPSD0:     SD Card           15193MB,LBA
+Video 0     TMS0:       CRT               Text,40x24
+Sound 0     SND0:       AY-3-8910         3+1 CHANNELS
+
+

Rebooting the System

+

The ‘R’ command within the Boot Loader performs a software reset of the +system. The system will perform a startup just like powering up or +pressing the hardware reset button (although the hardware is not +physically reset).

+

There is generally no need to do this, but it can be convenient when you +want to see the boot messages again or ensure your system is in a clean +state.

+
Boot [H=Help]: r
+
+Restarting System...
+
+

Setting NVRAM Options

+

On systems with RTC devices (that have Non-Volatile RAM), RomWBW +supports storing some limited configuration option options inside this +NVRAM.

+

Several configuration options are currently supported, these are known +as Switches

+
    +
  • Specify Automatic boot at startup, after an optional delay (AB)
  • +
  • Define the Disk or ROM App to be booted at for automatic boot (BO)
  • +
+

RomWBW uses bytes located at the start of RTC NVRAM, and includes a +checksum of the bytes in NVRAM to check for integrity before using the +configuration.

+

Initially NVRAM has to be reset (with default values), before it can be +used. As well as setting defaults, it also writes the correct checksum, +and allows the NVRAM to be accessed and to store the RomWBW config.

+

This is an explicit step that must be done, as any existing data stored +is overwritten. If you are using NVRAM for other purposes, then you can +continue to do so so long as you do NOT perform this Reset step.

+

NVRAM may also need to be reset in these circumstances:

+
    +
  • When there has been a loss of power to the NVRAM.
  • +
  • When upgrading to a new RomWBW version, or a RomWBW version that has + new switches.
  • +
  • If the NVRAM has been overwritten by another application.
  • +
+

If you want to continue to use NVRAM in your applications you may want +to consider storing your data above the RomWBW Switch data.

+

To configure these options an inbuilt ROM application is provided which +can be accessed by the command “W” from the RomWBW boot menu.

+

This application is also built as a CP/M utility, but is not included on +an disk image, it is found in the Binary/Applications folder of the +RomWBW distribution.

+

For further guidance on using this application please see the section +“RomWBW System Configuration” in the RomWBW +Applications +document.

+

If your system has both a Front Panel as well as NVRAM, +be aware that the Front Panel switches take precedence over the NVRAM +configuration settings.

+

Note that the WizNet class of Network devices also contain NVRAM which +is entirely separate from the RomWBW configuration NVRAM described here. +A separate utility is used to set the WizNet NVRAM (see CP/NET Client +Setup).

+

RomWBW +Applications

+

Changing Console and Console Speed

+

Your system can support a number of devices for the console. They may be +VDU type devices or serial devices. If you want to change which device +is the console, the I menu option can be used to choose the unit +and its speed.

+

The command format is I <unit> [<baudrate>]

+

where \<unit> is the character unit to select and +\<baudrate> is the optional baud rate.

+

Supported baud rates are:

+
 75   450  1800   7200  38400  115200   460800  1843200
+150   600  2400   9600  28800  153600   614400  2457600
+225   900  3600  14400  57600  230400   921600  3686400
+300  1200  4800  19200  76800  307200  1228800  7372800
+
+

Here is an example of changing the console to unit #1 (the second +serial port) and switching the port to 9600 baud:

+
Boot [H=Help]: i 1 9600
+
+  Change speed now. Press a key to resume.
+
+  Console on Unit #1
+
+

At this point, the Boot Loader prompt will be displayed on character +unit #1.

+

Note that not all character devices support changing baud rates and some +only support a limited subset of the baud rates listed. If you attempt +to select an invalid baud rate for your system, you will get an error +message.

+

HBIOS Diagnostic Verbosity

+

The ‘V’ command of the Boot Loader allows you to view and optionally +change the level of diagnostic messages that RomWBW will produce. The +normal verbosity level is 4, which means to display only fatal errors. +You can increase this level to see more warnings when function calls to +RomWBW HBIOS detect problems.

+

The use of diagnostic levels above 4 are really intended only for +software developers. I do not recommend changing this under normal +circumstances.

+

Console Takeover

+

If your system has more than one character unit, then the Boot Loader +will “poll” all of the character devices for a request to make any of +the alternate character devices the active console. This is called a +console takeover request. This functionality must be enabled in the ROM +build configuration, but currently it is for all standard ROMs.

+

To request a console takeover, you just press the \<space> character +twice in a row at the port or terminal that you want to move the console +to. The terminal or communication software must be configured for +the default serial port speed and data bits for this to work.

+

A takeover request is only possible while the active console is showing +the Boot Loader prompt prior to typing any characters at the active +console. In other words, once you start typing at the active console +prompt, the takeover polling is suspended. If you have started typing +characters, you can press \<enter> at the active console to get a fresh +Boot Loader prompt and reactivate the polling.

+

If you have built a custom ROM that includes an automatic boot command +with a timeout, then performing a console takeover will abort the +timeout process and the automatic boot command will not be performed.

+

Front Panel

+

RomWBW supports the concept of a simple front panel. The following image +is a conceptual view of such a front panel. If your system has a front +panel, it should look similar to the RomWBW Front Panel.

+
+ + +
+ +

The LEDs in the top row of the panel are used for multiple purposes. +They are initially used to display the progress of the system boot. This +may help in diagnosing a hardware or configuration issue in a system +that does not progress far enough to display text output on the console. +The meaning of the LEDs is:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
O-------System Boot has started
OO------Common RAM bank activated
OOO-----HBIOS transitioned to RAM
OOOO----Basic initialization done
OOOOO---CPU detection complete
OOOOOO--System timer configured
OOOOOOO-Pre-console device init done
OOOOOOOOConsole activation
+

Once the system has booted, the LEDs are used to indicate disk device +activity. Each LED numbered 7-0 represents disk units 7-0. As each disk +device performs I/O, the LED will light while the disk is active. This +is only possible for the first 8 disk units.

+

The second row of the front panel is composed of switches that allow you +to control a few aspects of the system startup. The switches are also +re-read during warm boot, so confirm the switch settings are your +desired boot configuration before executing ‘REBOOT /W’.

+

The first two switches affect the device used as the initial console.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CRT/SerialSec/PriExplanation
CRTPriPrimary Cathode Ray Tube device (high speed console)
CRTSecSecondary Cathode Ray Tube device (high speed console)
SerialPriBoot Console is Primary Serial Port
SerialSecBoot Console is Secondary Serial Port
+

If not available (default): “Char Unit 0” is used

+

The final six switches allow you to select the desired boot device.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Auto / MenuDisk / ROMFloppy / HardROM/App/Boot Slice
421Explanation
MenuBoot to RomWBW Menu
AutoDiskFloppy###Boot Selected Floppy Disk Index
AutoDiskHard###Boot Selected Hard Disk Index
AutoROM###Boot selected ROM Index
+

If not available: Boot Loader Command Prompt
+‘–’ Ignored
+‘#’ bit flag to select any three bits 4,2,1

+

ROM or Hard Disk - First 8 Drive Images

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
4 2 1Floppy / Hard
+Drive Index
ROM Index
0 0 0ZeroMonitor
0 0 1OneBASIC
0 2 0TwoForth
0 2 1ThreeGame
4 0 0FourCP/M
4 0 1FiveZ-System
4 2 0SixNet Boot
4 2 1SevenUser
+ +

Disk Management

+

The systems supported by RomWBW all have the ability to use persistent +disk media. Some systems have disk interfaces built-in, while others +will require add-in cards. You will need to refer to the documentation +for your system for your specific options.

+

The RomWBW firmware provides a hardware abstraction layer, All disks +will work on all hardware variations. This means you can remove disk +media from one RomWBW system and put it in a different RomWBW system. +The only constraint is that the applications on the disk media must be +up to date with the firmware on the system being used.

+

Key Terminology/Concepts

+

The following important terminology applies

+

Disk (or Disk Drive)

+

The hardware storage device that RomWBW talks to. RomWBW supports a +variety of storage disk device types.

+
    +
  • ROM Disk - RomWBW firmware - containing CPM utilities
  • +
  • RAM Disk - A section of system RAM initially empty
  • +
  • Floppy Disk(s) - Removable media
  • +
  • Hard Disk(s) - Includes CF Cards, SD Cards, USB Stick, etc.
  • +
+

The different disk types are further defined in the section Disk +Types.

+

Media

+

The storage device inserted into a disk drive, e.g. a floppy disk, CF +Card, SD Card, etc.

+

Slice

+

For hard disks a Slice is a smaller logical block of disk space that is +allocated and formatted with a filesystem and typically allocated to a +Drive letter. Slices allow large modern storage media to be sliced up +into smaller units compatible with CP/M. Slices should not be confused +with partitions, a slice is not a partition.

+

The concept of slices is described in detail in the section Hard Disk +Slices.

+

Drive

+

The mapping of a hardware disk (and slice) to a Drive letter in an +operating system. A Drive has a file system installed on it

+

Disk Image

+

A disk image is a predefined image of a complete CP/M filesystem, or +filesystem(s), including any partition tables (for hard disk images). +Each disk image has the complete set of normal applications and tools +distributed with the associated operating system or application suite.

+

This comes in for form of a file which is suitable for copying directly +onto target media, using a modern computer. It is generally easier to +use these disk images than transferring files over individually. See the +section Disk Images for further details.

+

Startup Hardware Discovery

+

During startup RomWBW performs detection for hardware supported by your +platform. During startup you will see messages for any disk +interface(s), listing device types (e.g. FD:, IDE:, SD:), and any media +that has been found on these interfaces. The messages you see will vary +depending on your hardware and the media you have installed.

+

As an example, here are the messages you might see if you have an IDE +interface in your system with a single disk drive connected to the +primary side of the interface:

+
IDE: IO=0x80 MODE=MK4
+IDE0: 8-BIT LBA BLOCKS=0x00773800 SIZE=3815MB
+IDE1: NO MEDIA
+
+

See RomWBW +Hardware +for a complete list of the different device types supported.

+

If you do not see drive letters assigned as expected, refer to the prior +system boot messages to ensure media has been detected in the interface.

+

Each drive letter refers back to a specific disk hardware interface like +IDE0. This is important as it is telling you what each drive letter +refers to.

+

Mass storage disks (like IDE) will normally have multiple drive letters +assigned. The extra drive letters refer to additional “slices” on the +disk.

+

Once your system has working disk devices, they will be accessible from +any operating system you choose to run. Disk storage is available +whether you boot your OS from ROM or from the disk media itself.

+

Drive Letter Assignment

+

In legacy CP/M operating systems only 16 drive letters (A:-P:) available +to be assigned to disks Drive letters were generally mapped to disk +drives in a completely fixed way. For example, drive A: would always +refer to the first floppy disk drive.

+

RomWBW implements a much more flexible drive letter assignment mechanism +so that any drive letter can dynamically be assigned to any disk device, +or slice of media.

+

For clarification, CP/M cannot refer directly to disk devices, CP/M +only understands drive letters, so to access a given disk device it must +first be assigned to a drive letter.

+

As the operating system starts up, you should see a list of drive +letters assigned to the disk media you have installed. Here is an +example of the list of drive letter assignments made during the startup +of Z-System:

+
Configuring Drives...
+
+        A:=MD0:0
+        B:=MD1:0
+        C:=FD0:0
+        D:=FD1:0
+        E:=IDE0:0
+        F:=IDE0:1
+        G:=IDE0:2
+        H:=IDE0:3
+
+

Above you can see that:

+
    +
  • Drive A: has been assigned to MD0 which is the RAM disk device.
  • +
  • Drive B: has been assigned to MD1 which is the ROM disk device.
  • +
  • Drives C: and D: have been assigned to floppy disk drives.
  • +
  • Drives E: thru H: have been assigned to the IDE0 hard disk device. The + 4 entries for IDE0 are referring to the first 4 slices on that disk.
  • +
+

CP/M 3 and ZPM3 do not automatically display the assignments at startup, +but you can use ASSIGN to display them.

+

The assignments at boot will stay the same on each boot as long as you +do not make changes to your hardware configuration. i.e. If you insert +or remove an SD Card, CF Card or USB Stick, the drive assignments will +change at next boot.

+

Since drive letter assignments can change, you must be careful when +doing destructive things like using CLRDIR to make sure the drive +letter you use is referring to the desired media.

+

Drive assignments can be changed at any time, by the ASSIGN command. +Please see the section Assign Drive Letters for +further details.

+

Default Drive Letters

+

When an operating system is booted, RomWBW will automatically assign +drive letters to disk devices. The assignment process varies depending +on:

+
    +
  • the disk/slice you choose to boot from, and
  • +
  • the number, type, and sizes of mass storage devices available at boot
  • +
+

The A: drive letter is considered special by most CP/M operating systems +and is automatically used in some cases. e.g. submitting batch files, +and is expected to be a writable volume.

+

If you boot to a physical disk device, then the first drive letter (A:) +will be assigned to the disk/slice that you are booting from, and the +rest of the drive letters will be offset to accommodate this. By making +the selected disk/slice the A: drive, you can setup different +disks/slices for specific uses and just boot it, and the booted +operating system will be the A: drive

+

However when performing a ROM boot of an operating system, the first two +drive letters will be assigned to your RAM disk (A:) and your ROM disk +(B:). This provides the maximum compatibility with CP/M.

+

After the first drive letter is assigned (as well as the second drive +letter in the case of a ROM boot), RomWBW will assign additional drive +letters based on the disk drives in the system. Additional drive letters +will be assigned in the following order:

+
    +
  • RAM Disk
  • +
  • ROM Disk
  • +
  • Floppy Disk(s)
  • +
  • Hard Disk(s)
  • +
+

If a disk/slice was already assigned as the A: (or B:) drive letter, +then it will not be assigned again.

+

Floppy or removable disk drives will be assigned a drive letter +regardless of whether there is any media inserted at the time of boot.

+

In the case of hard disks, 1-8 drive letters will be assigned to the +initial 1-8 slices of the disk drive. The number of drive letters +assigned to each hard disk depends on the number of hard disks in the +system:

+
    +
  • 1 Hard Disk: 8 drive letters (slices)
  • +
  • 2 Hard Disks: 4 drive letters (slices) per disk
  • +
  • 3+ Hard Disks: 2 drive letters (slices) per disk
  • +
+

This somewhat complicated algorithm is used to try and maximize the +limited number of operating system drive letters available (16) to the +available disk devices as evenly as possible.

+

For hard disk devices which are treated as non-removable media, drive +letters will only be assigned to disk devices that actually contain +media. i.e. No drive letters will be assigned to an SD Card slot that +has no SD Card inserted.

+

Assign Drive Letters

+

The ASSIGN command is used to view or change the current drive letter +mappings. Any changes made to drive letter mappings take immediate +effect

+

Refer to RomWBW +Applications +for more information on use of the ASSIGN command.

+

Since drive letter assignments are easily changed at any time using the +ASSIGN command, you can customize your assignments as desired after +starting the operating system. Even better, you can use an auto-submit +batch file to customzie the assignments at startup without any user +intervention.

+

Disk Operations/Commands

+

With some understanding of how RomWBW presents disk space to the +operating systems, we need to go over the options for actually setting +up your disk(s) with content.

+

Preparing Media for First Use

+

You can initialize the media in-place using your RomWBW system. +Essentially, this means you are creating a set of blank directories on +your disk so that files can be saved there. This is somewhat analogous +to partitioning of a hard disk or doing a low level format of a floppy +disk.

+

Initilizing a Floppy disk is covered in the section Floppy Disk +Formatting, or for a Hard disk the section +Hard Disk Preparation covers the steps to +manually setup a hard disk for first use.

+

Clearing (Formatting) Drives

+

This is somewhat analogous to doing a FORMAT operation on other systems.

+

With RomWBW you use the CLRDIR command to do this. This command is +merely “clearing out” the directory space of the drive referred to by a +drive letter and setting up the new empty directory.

+

Refer to RomWBW +Applications +for more information on use of the CLRDIR command.

+

Since CLRDIR works on drive letters, make absolutely sure you know +what media and slice are assigned to that drive letter before using +CLRDIR because CLRDIR will wipe out any pre-existing contents of the +slice.

+

After CLRDIR completes, the slice should be ready to use by the +operating system via the drive letter assigned. Start by using the DIR +command on the drive. This should return without error, but list no +files.

+

Here is an example of using CLRDIR. In this example, the ASSIGN +command is used to show the current drive letter assignments. Then the +CLRDIR command is used to initialize the directory of drive ‘G’ which +is slice 2 of hard disk device IDE0 (“IDE0:2”).

+
B>ASSIGN
+
+   A:=MD0:0
+   B:=MD1:0
+   C:=FD0:0
+   D:=FD1:0
+   E:=IDE0:0
+   F:=IDE0:1
+   G:=IDE0:2
+   H:=IDE0:3
+
+B>CLDIR G:
+CLRDIR Version 1.2B May 2024 by Max Scane
+
+Warning - this utility will overwrite the directory sectors of Drive: G
+Type CAPITAL Y to proceed, any key other key to exit. Y
+Directory cleared.
+B>
+
+

Checking Disk Layout

+

If you are not sure which disk layout is used for your existing media, +you can use the CP/M 2.2 STAT command to display information including +the number of “32 Byte Directory Entries” for a drive letter on the +corresponding hard disk.

+
    +
  • If it indicates 512, your disk layout is legacy (hd512).
  • +
  • If it indicates 1024, your disk layout is modern (hd1k).
  • +
+

Here is an example of checking the disk layout.

+
B>STAT E:DSK:
+
+    E: Drive Characteristics
+65408: 128 Byte Record Capacity
+ 8176: Kilobyte Drive  Capacity
+ 1024: 32  Byte Directory Entries
+    0: Checked  Directory Entries
+  256: Records/ Extent
+   32: Records/ Block
+   64: Sectors/ Track
+    2: Reserved Tracks
+
+

It is critical that you include DSK: after the drive letter in the +STAT command line. The important line to look at is labeled “32 Byte +Directory Entries”.

+

Disk Types

+

RAM & ROM Disks

+

A typical RomWBW system has 512KB of ROM and 512KB of RAM. Some portions +of each are dedicated to loading and running applications and operating +system. The space left over is available for an operating system to use +as a pseudo-disk device (ROM Disk and RAM Disk).

+

Unlike other types of disk devices, ROM and RAM Disks do not contain an +actual operating system and are not “bootable”. However, they are +accessible to any operating system (whether the operating system is +loaded from ROM or a different disk device).

+

Neither RAM nor ROM disks require explicit formatting or initialization. +ROM disks are pre-formatted and RAM disks are formatted automatically +with an empty directory when first used.

+

RAM Disk

+

The RAM disk provides a small CP/M filesystem that you can use for the +temporary storage of files. Unless your system has a battery backed +mechanism for persisting your RAM contents, the RAM disk contents will +be lost at each power-off.

+

The RAM disk is an excellent choice for storing temporary files because +it is very fast. You will notice that the first time an operating system +is started after the power was turned off, you will see a message +indicating that the RAM disk is being formatted. If you reset your +system without turning off power, the RAM disk will not be reformatted +and it’s contents will still be intact.

+

ROM Disk

+

Like the RAM disk, the ROM disk also provides a small CP/M filesystem, +but it’s contents are static – they are part of the ROM. As such, you +cannot save files to the ROM disk. Any attempt to do this will result in +a disk I/O error.

+

The contents of the ROM disk have been chosen to provide a core set of +tools and applications that are helpful for either CP/M 2.2 or ZSDOS. +Since ZSDOS is CP/M 2.2 compatible, this works fairly well. However, you +will find some files on the ROM disk that will work with ZSDOS, but will +not work on CP/M 2.2. For example, LDDS, which loads the ZSDOS +date/time stamper will only run under ZSDOS.

+

Flash ROM Disks

+

The limitation of ROM disks being read-only can be overcome on some +platforms with the appropriate selection of Flash ROM chip and system +configuration. In this case the flash-file system can be enabled which +will allow the ROM disk to be read and written to. Flash devices have a +limited write lifespan and continual usage will eventually wear out the +device. It is not suited for high usage applications. Enabling ROM disk +writing requires building a custom ROM.

+

Floppy Disks

+

If your system has the appropriate hardware, RomWBW will support the use +of floppy disks. The supported floppy disk formats are generally derived +from the IBM PC floppy disk formats:

+
    +
  • 5.25” 360K Double-sided, Double-density
  • +
  • 5.25” 1.2M Double-sided, High-density
  • +
  • 3.5” 720K Double-sided, Double-density
  • +
  • 3.5” 1.44M Double-sided, High-density
  • +
+

When supported, RomWBW is normally configured for 2 3.5” floppy disk +drives. If a high-density disk drive is used, then RomWBW automatically +detects and adapts to double-density or high-density media. It cannot +automatically detect 3.5” vs. 5.25” disk drive types – the ROM must be +pre-configured for the disk drive type.

+

WARNING: Some of the operating systems provided with RomWBW require +that a soft-reset be performed when swapping floppy disk media. For +example, under CP/M 2.2, you must press control-C at the CP/M prompt +after inserting a new floppy disk. The consequences of failing to +perform the soft-reset vary from unexpected error messages to full disk +directory corruption.

+

Hard Disks

+

The concept of a hard disk in RomWBW applies to any storage device that +provides at least 8MB of space. The actual media can be a real spinning +hard disk, a CompactFlash Card, a SD Card, etc. In this document, the +term hard disk will apply equally to all of these.

+

The vintage operating systems included with RomWBW were produced at a +time when mass storage devices were quite small. CP/M 2.2 could only +handle filesystems up to 8MB.

+

Since storage devices today are quite large, RomWBW implements a +mechanism called slicing (see Hard Disk Slices) to +allow up to 256 8MB CP/M filesystems on a single large storage device, +where each slice can be assigned to a drive letter in CPM, and be +treated as its own hard disk drive (from a CPM perspective).

+

In order to achieve compatibility across all of the operating systems +supported by RomWBW, the hard disk filesystem format used is 8MB. This +ensures any filesystem will be accessible to any of the operating +systems.

+

RomWBW uses Logical Block Addressing (LBA) to interact with all hard +disks. The RomWBW operating systems use older Cylinder/Head/Sector (CHS) +addressing. To accommodate the operating systems, RomWBW emulates CHS +addressing. Specifically, it makes all hard disks look like they have 16 +sectors and 16 heads. The number of tracks varies with the size of the +physical hard disk.

+

Hard Disk Layouts

+

When RomWBW uses a hard disk, it utilizes an area of the physical hard +disk drive space to store a sequential series of slices that contain the +actual CP/M filesystems referred to by drive letters by the operating +system.

+

Two hard disk layout schemes exist:

+
    +
  • Modern (hd1k)
  • +
  • Legacy (hd512)
  • +
+

You cannot mix disk layouts on a single disk device, however It is +perfectly fine for one system to have multiple hard disks with different +layouts – each physical disk device is handled separately.

+

If you are setting up a new disk, the modern (hd1k) layout is +recommended for the following reasons:

+
    +
  • Larger number of directory entries per filesystem
  • +
  • Simplifies creation of coresident FAT filesystem
  • +
  • Reduces chances of data corruption
  • +
  • Each slice occupies exactly 8MB (an exact power of 2) in size
  • +
+

Both the legacy and modern disk layouts continue to be fully supported +by RomWBW. There are no plans to deprecate the legacy layout.

+

Modern Layout

+

RomWBW (Starting with v3.2) supports the use of disk partitioning, +utilising a Master Boot Record (MBR) partition tables. The Wikipedia +article on the Master Boot +Record is excellent +if you are not familiar with them.

+

RomWBW uses the partition type id 0x2E. This partition type id does +not equate to any existing well-known partition types – it was chosen +because it is not generally used. RomWBW does not support extended +partitions – only a single primary partition can be used.

+

The existence of a partition table entry for RomWBW on a hard disk makes +it behave in the modern mode. Removing the RomWBW partition entry from a +modern hard disk layout will cause the existing data to be unavailable +and/or corrupted

+

The CP/M filesystem in the slices of the modern disk layout contain 1024 +directory entries.

+

Legacy Layout

+

Originally, RomWBW always used the very start of the hard disk media for +the location of the slices. In this layout, slice 0 referred to the +first chunk of ~8MB on the disk, slice 1 referred to the second chunk of +~8MB on the disk, and so on. The number of slices is limited to the size +of the disk media – if you attempted to read/write to a slice that would +exceed the disk size, you would see I/O errors.

+

The legacy format takes steps to allow a partition table to still be +used for other types of filesystems such as DOS/FAT. It just does not +use a partition table entry to determine the start of the RomWBW slices.

+

The lack of a RomWBW partition table entry will cause legacy behaviour. +Adding a partition table entry on an existing legacy RomWBW hard disk +will cause the existing data to be unavailable and/or corrupted.

+

The CP/M filesystem in the slices of the legacy disk layout contain 512 +directory entries.

+

Hard Disk Slices

+

RomWBW implements a mechanism called slicing to allow multiple CP/M +filesystem on a single large storage device. To say it another way, the +media is “sliced up” into many CP/M filesystems.

+

You cannot use slices on any media less than 8MB in size. Specifically, +you cannot slice RAM disks, ROM disks, floppy disks, etc. All of these +are considered to have a single slice (0)

+

It is very important to understand that RomWBW slices are not +individually created or allocated on your hard disk. RomWBW uses a +single partition on your hard disk to contain the slices. You should +think of slices as just an index into a sequential set of 8MB areas that +exist in this partition.

+

RomWBW allows up to up to 256 slices each of 8MB in size on a single +large storage device. This allows the use of up to 2GB of usable space +on one media device.

+

It is possible to create other partitions (typically FAT), for now, we +are just talking about the slices within the single RomWBW partition.

+

Slice Assignment

+

When assigning Hard disks to drive letters you also need to assign the +slice.

+

Referring to slices within a storage device is done by appending a +:<n> where \<n> is the device relative slice number from 0-255. For +example, if you have an IDE device, it will show up as IDE0: in the boot +messages meaning the first IDE device. To refer to the fourth slice of +IDE0, you would type “IDE0:3”. Here are some examples:

+ + + + + + + + + + + + + + + + + + + + + +
IDE0:0First slice of disk in IDE0
IDE0:First slice of disk in IDE0
IDE0:3Fourth slice of disk in IDE0
+

So, if you wanted to use drive letter L: to refer to the fourth slice of +IDE0, you could use the command ASSIGN L:=IDE0:3. There are a couple +of rules to be aware of when assigning drive letters. First, you may +only refer to a specific device/slice with one drive letter at a time. +Said another way, you cannot have multiple drive letters referring to a +the same device/slice at the same time. Second, there must always be a +drive assigned to A:. Any attempt to violate these rules will be blocked +by the ASSIGN command.

+

As you see, the name of a slice does not reference the hard disk +partition containing the slices. Since there can only be a single RomWBW +partition containing slices on any disk, the partition is determined +automatically.

+

RomWBW does not prevent you from assigning slices to drive letters even +if the location of the slice does not fit on the physical disk. Any +attempt to access a drive letter mapped to a slice that does not fit +will result in an error such as “no disk” from the operating system.

+

For example, a 64MB CF Card (which is typically a bit smaller than 64MB) +will only fit 7 slices. At startup, you will typically see 8 drive +letters assigned to the CF Card. Attempting to access the last drive +letter will result in a “no disk” error from the operating system.

+

Hard Disk Capacity

+

The exact number of CP/M filesystem slices that will fit on your +specific physical hard disk can be determined as follows:

+
    +
  • For modern (hd1k) disk layouts, it is 1024KB + (slices * 8192KB). Or + equivalent to say 1MB + (slices * 8MB).
  • +
  • For legacy (hd512) disk layouts, it is slices * 8,320KB.
  • +
+

WARNING: In this document KB means 1024 bytes and MB means 1048576 +bytes (frequently expressed as KiB and MiB in modern terminology). In +general, hard disk capacities use KB to mean 1000 bytes and MB to mean +1,000,000 bytes.

+

As an example, A “64MB” CF Card probably has less than 62.5MB of actual +space (using the RomWBW definition that 1MB is 1048576 bytes). Such a +drive will not support 8 slices. It will support 7 slices just fine +because 1024KB + (7 * 8192MB) = 57MB (hd1k) or 7 * 8,320KB = 58.24MB +(hd512)

+

Although you can use up to 256 slices per physical disk, equating to 2GB +of storage this large number of slices is rarely used. It is recommended +that hard disk media used with RomWBW be 1GB or greater in capacity. +This will support the RomWBW Combo Disk Image (see Combo Hard Disk +Image) that allows you to use 64 CP/M +filesystem slices and a 384KB FAT filesystem.

+

Disk Preparation

+

There are two approaches to preparing disks for use by RomWBW.

+
    +
  • Manual: Use RomWBW itself to format empty disks and then transfer + files over to the disks.
  • +
  • Images: Use a modern computer to write a pre-built disk image + including files to a disk.
  • +
+

This section of the document describes the manual process of preparing +empty disks that are ready for use by an operating system.

+

Alternatively, you can use the pre-built RomWBW disk images to quickly +create disk media that already has a large selection of files and +bootable operating system slices. Using images to prepare a disk is +documented in Disk Images. You do not need to follow the +instructions in this section if you want to use disk images.

+

Floppy Disk Formatting

+

Floppy media must be physically formatted before it can be used. This is +normally accomplished by using the supplied Floppy Disk Utility FDU +application. This application interacts directly with your hardware and +therefore you must specify your floppy interface hardware at application +startup. Additionally, you need to specify the floppy disk drive and +media format to use for formatting.

+

Refer to RomWBW +Applications +for more information on use of the FDU command.

+

Since the physical format of floppy media is the same as that used in a +standard MS-DOS/Windows computer, you can also format floppy disk media +in a standard computer. However there are caveats:

+
    +
  • The directory format itself will NOT be compatible with CP/M OSes. + You WILL need to use the CLRDIR command to reformat the + directory area from CP/M. See section Clearing (Formatting) + Drives
  • +
  • FDU allows you to specify physical sector interleaving (defaults to 2) + which will result in faster floppy disk I/O. Formatting on a modern + computer may not optimize this.
  • +
+

Below is a sample session using FDU to format a 1.44M floppy disk in +the first (primary) floppy disk drive:

+
B>FDU
+
+Floppy Disk Utility (FDU) v5.8, 26-Jul-2021 [HBIOS]
+Copyright (C) 2021, Wayne Warthen, GNU GPL v3
+
+SELECT FLOPPY DISK CONTROLLER:
+  (A) Disk IO ECB Board
+  (B) Disk IO 3 ECB Board
+  (C) Zeta SBC Onboard FDC
+  (D) Zeta 2 SBC Onboard FDC
+  (E) Dual IDE ECB Board
+  (F) N8 Onboard FDC
+  (G) RCBus SMC (SMB)
+  (H) RCBus WDC (SMB)
+  (I) SmallZ80 Expansion
+  (J) Dyno-Card FDC, D1030
+  (K) RCBus EPFDC
+  (L) Multi-Board Computer FDC
+  (X) Exit
+=== OPTION ===> D-IDE
+
+===== D-IDE ===========<< FDU MAIN MENU >>======================
+(S)ETUP: UNIT=00  MEDIA=720KB DS/DD    MODE=POLL        TRACE=00
+----------------------------------------------------------------
+(R)EAD          (W)RITE         (F)ORMAT        (V)ERIFY
+(I)NIT BUFFER   (D)UMP BUFFER   FDC (C)MDS      E(X)IT
+=== OPTION ===> SETUP
+ENTER UNIT [00-03] (00):
+00: 3.5" 720KB - 9 SECTORS, 2 SIDES, 80 TRACKS, DOUBLE DENSITY
+01: 3.5" 1.44MB - 18 SECTORS, 2 SIDES, 80 TRACKS, HIGH DENSITY
+02: 5.25" 320KB - 8 SECTORS, 2 SIDES, 40 TRACKS, DOUBLE DENSITY
+03: 5.25" 360KB - 9 SECTORS, 2 SIDES, 40 TRACKS, DOUBLE DENSITY
+04: 5.25" 1.2MB - 15 SECTORS, 2 SIDES, 80 TRACKS, HIGH DENSITY
+05: 8" 1.11MB - 15 SECTORS, 2 SIDES, 77 TRACKS, DOUBLE DENSITY
+06: 5.25" 160KB - 8 SECTORS, 1 SIDE, 40 TRACKS, DOUBLE DENSITY
+07: 5.25" 180KB - 9 SECTORS, 1 SIDE, 40 TRACKS, DOUBLE DENSITY
+08: 5.25" 320KB - 8 SECTORS, 1 SIDE, 80 TRACKS, DOUBLE DENSITY
+09: 5.25" 360KB - 9 SECTORS, 1 SIDE, 80 TRACKS, DOUBLE DENSITY
+ENTER MEDIA [00-09] (00): 01
+00: POLLING (RECOMMENDED)
+01: INTERRUPT (!!! READ MANUAL !!!)
+02: FAST INTERRUPT (!!! READ MANUAL !!!)
+03: INT/WAIT (!!! READ MANUAL !!!)
+04: DRQ/WAIT (!!! NOT YET IMPLEMENTED!!!)
+ENTER MODE [00-04] (00):
+ENTER TRACE LEVEL [00-01] (00):
+
+===== D-IDE ===========<< FDU MAIN MENU >>======================
+(S)ETUP: UNIT=00  MEDIA=1.44MB DS/HD   MODE=POLL        TRACE=00
+----------------------------------------------------------------
+(R)EAD          (W)RITE         (F)ORMAT        (V)ERIFY
+(I)NIT BUFFER   (D)UMP BUFFER   FDC (C)MDS      E(X)IT
+=== OPTION ===> FORMAT (T)RACK, (D)ISK ===> DISK
+ENTER INTERLEAVE [01-12] (02):
+
+RESET DRIVE...
+PROGRESS: TRACK=4F HEAD=01 SECTOR=01
+
+===== D-IDE ===========<< FDU MAIN MENU >>======================
+(S)ETUP: UNIT=00  MEDIA=1.44MB DS/HD   MODE=POLL        TRACE=00
+----------------------------------------------------------------
+(R)EAD          (W)RITE         (F)ORMAT        (V)ERIFY
+(I)NIT BUFFER   (D)UMP BUFFER   FDC (C)MDS      E(X)IT
+=== OPTION ===> EXIT
+
+

You can confirm a floppy disk is ready for content by simply running a +DIR command on it. The DIR command should complete without error and +should list no files.

+

Hard Disk Preparation

+

This section deals with initializing hard disk media entirely from your +RomWBW system. The following instructions are one way to proceed. This +does not mean to imply it is the only possible way.

+

First you need to understand

+
    +
  • The disk layout approach (either hd1k or the legacy hd512). See Hard + Disk Layouts section if you are not sure. hd1k + should be the preferred layout.
  • +
  • The number of 8MB slices that you want to allocate, preferred is 64 + slices. At least 1 slice of 8MB is required
  • +
  • If you want to leave space for a FAT partition. See FAT Filesystem + Preparation
  • +
  • The total capacity of your drive, to hold the CP/M (and other) + partition(s)
  • +
+

Then you will need to start by inserting the disk media, booting RomWBW, +and confirming that the media is being recognized. If RomWBW recognizes +the media, it will indicate this in the boot messages even though the +media may not yet been prepared for use.

+

Then launch either CP/M 2.2 or Z-System from ROM using the Boot Loader +C or Z commands respectively. You can now use the tools on the ROM +disk to prepare your disks.

+

Note that you may see the operating system assign disks/slices to drives +letters even though the disks/slices are not yet initialized. This is +normal and does not mean the disks/slices are ready to use.

+

Partition Setup

+

To setup a partition you must run the FDISK80 utility. After FDISK80 +starts, enter the disk unit number of the new media. The disk unit +number was assigned at boot See Device Unit +Assignments

+

Refer to RomWBW +Applications +for more information on use of the FDISK80 utility.

+

If you want to use the legacy hd512 layout skip down to the Legacy +(hd512) section

+

Modern (hd1k)

+

At this point, use the I command to initialize (reset) the partition +table to an empty state.

+

You must create a partition for the RomWBW CP/M slices. Then create a +partition using the N command. Importantly:

+
    +
  • The partition number should typically be 1 the first partition
  • +
  • The partition can be placed anywhere you want, The typical location + for the RomWBW partition is at 1MB.
  • +
  • The partition size should be the total size of all the slices you + require, and must be at least 8MB in size, in increments of 8MB makes + sense.
  • +
+

You must then set the type of partition to 2E using the T +command. The P command can be used to display the partition before it +is written Finally the partition can be written to disk using the W +write command.

+

WARNING: Modifying the partition table of existing media will make +any data on the media inaccessible.

+

Below is an example of creating a RomWBW partition following these +guidelines.

+
FDISK80 for RomWBW, UNA, Mini-M68k, KISS-68030, SBC-188  ----
+       Version 1.1-22 created 7-May-2020
+                 (Running under RomWBW HBIOS)
+
+HBIOS unit number [0..11]: 4
+Capacity of disk 4:  (  4G)  7813120      Geom 77381010
+Nr  ---Type- A --      Start         End   LBA start  LBA count  Size
+ 1             00       *** empty ***
+ 2             00       *** empty ***
+ 3             00       *** empty ***
+ 4             00       *** empty ***
+>>i
+>>n
+New partition number: 1
+Starting Cylinder (default 0): 1Mb
+Ending Cylinder (or Size= "+nnn"): +512Mb
+>>t
+Change type of partition number: 1
+New type (in hex), "L" lists types: 2e
+>>p
+Nr  ---Type- A --      Start         End   LBA start  LBA count  Size
+ 1    RomWBW   2e      8:0:1  1023:15:16        2048    1048576  512M
+ 2             00       *** empty ***
+ 3             00       *** empty ***
+ 4             00       *** empty ***
+>>w
+Do you really want to write to disk? [N/y]: y
+Okay
+FDISK exit.
+
+

At this point, it is best to restart your system to make sure that the +operating system is aware of the partition table updates. Start CP/M 2.2 +or Z-System from ROM again.

+

Legacy (hd512)

+

At this point, use the I command to initialize (reset) the partition +table to an empty state.

+

To use the hd512 layout, use W to write the empty table to the disk +and exit. Remember that the lack of a partition for RomWBW implies the +legacy (hd512) layout.

+

At this point, it is best to restart your system to make sure that the +operating system is aware of the partition table updates. Start CP/M 2.2 +or Z-System from ROM again.

+

FAT Partition

+

At this point you may want to consider creating a FAT partition Please +see the section FAT Filesystem +Preparation for detils on how to setup the +FAT partition.

+

Slice Initialization

+

You need to initialize each slice for CP/M to use it. This is somewhat +analogous to doing a FORMAT operation on other systems, and is done +using the CLRDIR command.

+

This is covered in the section Clearing (Formatting) +Drives

+

WARNING: Earlier versions of the CLRDIR application do not appear +to check for disk errors when it runs. If you attempt to run CLRDIR on +a drive that is mapped to a slice that does not actually fit on the +physical disk, it may behave erratically.

+

Assuming you want to use additional slices, you should initialize them +using the same process. You may need to reassign drive letters to access +some slices that are beyond the ones automatically assigned. You can use +the ASSIGN command to handle this.

+

Post Disk Preparation

+

Once a disk (either floppy or hard disk) has been initialised and +formattted you may optionally; * Make the disk bootable * Copy system +(or other) files to the disk

+

Making a Disk Bootable

+

To make a disk bootable you will need to follow the specific +instructions in Operating Systems, as each +operating system will be different.

+

Generally you will need to use SYSCOPY to setup the system track(s) of +the disk.As an example, If you wanted to setup C: as a bootable Z-System +disk you would use:

+
B>SYSCOPY C:=B:ZSYS.SYS
+
+SYSCOPY v2.0 for RomWBW CP/M, 17-Feb-2020 (CP/M 2 Mode)
+Copyright 2020, Wayne Warthen, GNU GPL v3
+
+Transfer system image from B:ZSYS.SYS to C: (Y/N)? Y
+Reading image... Writing image... Done
+
+

Once this process succeeds, you will be able to boot directly to the +disk slice from the boot loader prompt. See the instructions in +Starting Operating Systems from +Disk for details on this.

+

Copying System Files

+

As well as making the disk bootable, you may need to transfer other +system and application files to your disks. Refer to Transferring +Files for more information on getting files onto +your disks.

+

Disk Images

+

Since it would be quite a bit of work to transfer over all the files you +might want initially to your disk(s), It is generally easier to use +these disk images than transferring your files over individually. RomWBW +comes with a variety of ready to use disk images.

+

You can use your modern Windows, Linux, or Mac computer to copy a disk +image onto the disk media, then just move the media over to your RomWBW +computer.

+

The disk image files are found in the Binary directory of the +distribution.

+

Each disk image has the complete set of normal applications and tools +distributed with the associated operating system or application suite. +The following table shows the disk images available.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Disk ImageDescriptionBoot
xxx_aztec.imgAztec C CompilerNo
xxx_bascomp.imgMicrosoft Basic-80 CompilerNo
xxx_blank.imgempty imageNo
xxx_cowgol.imgCowgol 2.0 CompilerNo
xxx_cpm22.imgDRI CP/M 2.2 Operating SystemYes
xxx_cpm3.imgDRI CP/M 3 Operating SystemYes
xxx_dos65.imgDOS/65 Operating SystemYes
xxx_fortran.imgMicrosoft Fortran-80 CompilerNo
xxx_games.imgGames Disk for CP/MNo
xxx_hitechc.imgHI-TECH Z80 CP/M C compilerNo
xxx_msxroms1.imgMSX ROMs Disk 1No
xxx_msxroms2.imgMSX ROMs Disk 2No
xxx_nzcom.imgNZCOM ZCPR 3.4 Operating SystemYes
xxx_qpm.imgQPM Operating SystemYes
xxx_tpascal.imgBorland Turbo Pascal CompilerNo
xxx_ws4.imgWordStar v4 & ZDE ApplicationsNo
xxx_z80asm.imgRelocating macro assembler for CP/MNo
xxx_zpm3.imgZPM3 Operating SystemYes
xxx_zsdos.imgZCPR-DJ & ZSDOS 1.1 Operating SystemYes
+

You will find 3 sets of these .img files in the distribution. The “xxx” +portion of the filename will be:

+
    +
  • “fd_” for a floppy image.
  • +
  • “hd1k_” for a modern layout hard disk image.
  • +
  • “hd512_” for a legacy layout hard disk image.
  • +
+

In the case of xxx_dos65.img, only an hd512 variant is provided. This is +a constraint of the DOS65 distribution.

+

There is also an image file called “psys.img” which contains a bootable +p-System hard disk image. It contains 6 p-System filesystem slices, but +these are not interoperable with the CP/M slices described above. This +file is discussed separately under UCSD p-System in +Operating Systems section.

+

Floppy Disk Images

+

The floppy disk images are all intended to be used with 3.5” +high-density, double-sided 1.44 MB floppy disk media. This is ideal for +the default floppy disk drive support included in RomWBW standard ROMs.

+

For floppy disks, the .img file is written directly to the floppy media +as is. The floppy .img files are 1.44 MB which is the exact size of a +single 3.5” high density floppy disk. You will need a floppy disk drive +of the same type connected to your modern computer to write this image. +Although modern computers do not come equipped with a floppy disk drive, +you can still find USB floppy drives that work well for this.

+

The floppy disk must be physically formatted before writing the +image onto it. You can do this with RomWBW using FDU as described in +the Floppy Disk Formatting section of this +document. While you can also format the floppy using your modern +computer, using FDU is preferable.

+

RomWBW includes a Windows application called RawWriteWin in the Tools +directory of the distribution. This simple application will let you +choose a file and write it to an attached floppy disk drive. For +Linux/MacOS, I think you can use the dd command (but I have not actually +tried this). It is probably obvious, but writing an image to a floppy +disk will overwrite and destroy all previous contents.

+

Once the image has been written to the floppy disk, you can insert the +floppy disk in your RomWBW floppy disk and read/write files on it +according to the specific operating system instructions. If the image is +bootable, then you will be able to boot from it by entering the floppy +disk drive’s corresponding unit number at the RomWBW Boot Loader command +prompt.

+

Hard Disk Images

+

Keeping in mind that a RomWBW hard disk (including CF/SD/USB devices) +allows you to have multiple slices (CP/M filesystems), there are a +couple ways to image hard disk media. The easiest approach is to use the +Combo Disk Image. This hard disk image is already prepared with 6 slices +containing 5 ready-to-run OSes and a slice with the WordStar application +files.

+

Alternatively, you can create your own hard disk image with the specific +slice contents you choose.

+

Standard Hard Disk Layout

+

As previously described in Hard Disk Layouts, the +exact placement of slices and optional FAT partition will vary depending +on which disk layout (hd512 or hd1k) you are using and your partition +table entries. To simplify the use of hard disk images, RomWBW has +adopted a standard partition layout for disk image files provided. This +standard layout is used to produce the Combo Disk Images described +below.

+

These partition sizes and locations were chosen to:

+
    +
  • Fit entirely on 1GB media
  • +
  • Allow for 64 CP/M filesystem slices
  • +
  • Allow for a 384KB FAT filesystem
  • +
+

The standard partition table table entries are:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
— Modern (hd1k) —— Legacy (hd512) —
Byte(s)Sector(s)Byte(s)Sector(s)
RomWBW Partition Start1 MB2,048
RomWBW Partition Size512 MB1,048,576
FAT Filesystem Start513 MB1,050,624520 MB1,064,960
FAT Filesystem Size384 MB786,432384 MB786,432
\<end>897 MB1,851,392904 MB1,837,056
+

NOTE: RomWBW is not limited to these partition table entries. You +can change the size and location of the RomWBW and/or FAT partitions to +increase/decrease the number of slices or FAT filesystem size. Doing so +would require using FDISK80 to define your own custom disk layout and +initializing your filesystems manually.

+

The RomWBW System +Guide +has more information on the standard disk layouts as implemented in the +Combo Disk Images. Additionally, there is a document called “Hard Disk +Anatomy.pdf” in the Doc directory of the RomWBW distribution with +detailed information on the standard disk layouts.

+

Combo Hard Disk Image

+

The Combo Disk Image is essentially just a single disk image that has +several of the individual filesystem images (slices) already +concatenated together using the standard disk layout described above. +The Combo Disk Image includes the partition table of the standard disk +layout and the following 6 slices in the positions indicated:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SliceDescription
Slice 0DRI CP/M 2.2 Operating System
Slice 1ZCPR-DJ & ZSDOS 1.1 Operating System
Slice 2NZCOM ZCPR 3.4 Operating System
Slice 3DRI CP/M 3 Operating System
Slice 4ZPM3 Operating System
Slice 5WordStar v4 & ZDE Applications
Slice 6-63blank unformatted
+

There are actually 2 Combo Disk Images in the distribution. One for an +hd512 disk layout (hd512_combo.img) and one for an hd1k disk layout +(hd1k_combo.img). Simply use the image file that corresponds to your +desired hard disk layout. Review the information in Hard Disk +Layouts if you need more information of the disk +layout options.

+
+

Note: Apart from the hd512 and hd1k Combo Disk Images (mentioned +above) there are actually a number of other hd1k_*_combo.img files. +These additional combo files are platform (generally romless) +specific, and should be ignored unless you are on one of these +platforms. If you are on one of these platforms you must use the +correct combo file

+
+

The Combo Disk Image actually only contains the initial partition table, +and the first 6 slices (Slice 0 to 5), this is approximately 49MB in +size. While the partition table reserves space to store 64 CP/M +filesystem slices as well as a single 384MB FAT filesystem, these areas +remain empty, and must be initialized manually using CLRDIR for CP/M +filesystems and FAT FORMAT for the FAT filesystem.

+

Combo Disk Image Capacity

+

The standard hard disk layout used by the Combo Disk Image was designed +to fit well on a 1GB hard disk. The 64 CP/M slices (approximately 512MB) +and 384MB FAT filesystem all fit well within a 1GB hard disk. This size +choice was a bit arbitrary, but based on the idea that 1GB CF/SD/USB +Media is easy and cheap to acquire.

+

It is fine if your hard disk is smaller than 1GB. It just means that it +will not be possible to use the pre-allocated FAT filesystem partition +and any CP/M filesystem slices that don’t fit. The true number of CP/M +filesystem slices that will fit on your specific physical hard disk can +be calculated as described in Hard Disk Capacity.

+

If you attempt to access a slice past the end of the physical hard disk +you will get “no disk” errors. You should calculate the maximum number +of slices your hard disk will support and do not exceed this number.

+

Combo Disk Image Advice

+

A great way to maintain your own data on a hard disk is to put your data +in slices beyond the first 6. By doing so, you can always “re-image” +your drive media with the Combo Disk Image without overlaying the data +stored in the slices beyond the first 6. Just be very careful to use the +same combo image layout (hd512 or hd1k) as you used originally.

+

Custom Hard Disk Image

+

For hard disks, each .img file represents a single slice (CP/M +filesystem). Since a hard disk can contain many slices, you can just +concatenate the slices (.img files) together to create your desired hard +disk image.

+

If you look in the Binary directory of the distribution, you will see +that there are more disk (slice) images than the 6 that are included in +the Combo Disk Images. These supplemental disk images are identified by +looking for the files that start with hd1k_ or hd512_.

+

Adding Slices to Combo Image

+

You can add slices to the Combo Disk Images simply by tacking slices +onto the end. For example, if you want to add a slice containing the MSX +ROMs to the end of the combo image, you could use one of the following +command lines depending on your operating system:

+

Windows:

+

COPY /B hd1k_combo.img + hd1k_msxroms.img my_hd.img

+

Linus/MaxOS:

+

cat hd1k_combo.img hd1k_msxroms.img >my_hd.img

+

Note that you must be sure to use either the hd1k_ or hd512_ +prefixed files together. You cannot mix them.

+

Creating a new Custom Image

+

If you want to create a completely custom hard disk image that is not +based on the existing combo image, you can generate a disk image +entirely from scratch using whatever slices you want in whatever order +you like.

+

For example, if you want to create a hard disk image that has slices for +CP/M 2.2, CP/M 3, and WordStar in the hd512 format, you would use the +command line of your modern computer to create the final image:

+

Windows:

+

COPY /B hd512_cpm22.img + hd512_cpm3.img + hd512_ws hd.img

+

Linux/MacOS:

+

cat hd512_cpm22.img hd512_cpm3.img hd512_ws >hd.img

+

NOTE: For the hd1k disk layout, you must prepend the prefix file +called hd1k_prefix.dat which contains the required partition table. So, +for an hd1k layout you would use the following:

+

Windows:

+

COPY /B hd1k_prefix.dat + hd1k_cpm22.img + hd1k_cpm3.img + hd1k_ws hd.img

+

Linux/MacOS:

+

cat hd1k_prefix.dat hd1k_cpm22.img hd1k_cpm3.img hd1k_ws >hd.img

+
+

Note: Apart from the hd1k_prefix.dat file (mentioned above) there +are actaully a number of other hd1k_*_prefix.dat files. These +additional prefix files are platform (generally romless) specific, and +should be ignored unless you are on one of these platforms. If you are +on one of these platforms you must use the correct prefix file

+
+

In all of the examples above, the resulting file (hd.img) would now be +written to your hard disk media and would be ready to use in a RomWBW +system.

+

If you wish to further customize or create new disk image definitions, +please refer to the ReadMe.txt file in the Source/Images directory.

+

Writing Hard Disk Images

+

Once you have chosen a Combo Hard Disk Image file or prepared your own +custom hard disk image file, it will need to be written to the media +using your modern computer. When using this method, the disk will be +partitioned and setup with 1 or more slices containing ready-to-run +bootable operating systems.

+

To write a hard disk image file onto your actual media (actual hard disk +or CF/SD/USB Media), you need to use an image writing utility on your +modern computer. Your modern computer will need to have an appropriate +interface or slot that accepts the media. To actually copy the image

+
    +
  • On Linux or MacOS , you can use the dd command.
  • +
  • On Windows, in the “Tools” directory of the distribution, there is an + application called Win32DiskImager.
  • +
+

In all cases, the image file should be written to the media starting at +the very first block or sector of the media. This is the default +behaviour on all software.

+

To be entirely clear, writing a disk image file to your hard disk media +will overwrite an pre-existing partition table and the number of slices +that your image file contains. It will not overwrite or corrupt slices +beyond those in the image file. As a result, you can use additional +slices as a place to maintain your personal data because these slices +will survive re-imaging of the media. If you setup a FAT partition on +your media, it will also survive the imaging process.

+

Media Usage and Initialization

+

Once you have copied the image onto the hard disk media, you can move +the media over to your RomWBW system. You can then boot to the operating +system slices by specifying (\<diskunit>.\<slice>) at the RomWBW +Boot Loader command prompt. See the section Starting Operating Systems +from Disk for further details

+

You are not limited to the number of slices that are contained in the +image that you write to your hard disk media. You can use additional +slices as long your media has room for them.

+

However, writing the disk image will not initialize the additional +slices. You will need to use the CLRDIR application to initialize any +un-initialized slice before its first use, and and optionally SYSCOPY +if you want th slice to be bootable. If you use the combo image this +applies to slices 6 thru 63. The procedure for this is documented in the +Clearing (Formatting) Drives section.

+

Likewise, the pre-allocated FAT partition must still be formatted using +FAT FORMAT in order to actually use it (see FAT Filesystem +Preparation). Alternatively, the FAT +partition can be formatted on a modern computer.

+

Re-Imaging Existing Media

+

In order for your additional slices and/or FAT partition to survive +re-imaging, you must follow these rules:

+
    +
  • Do not modify the partition table of the media using FDISK80 or any + other partition management tools.
  • +
  • Ensure that your hard disk image file uses the same disk layout + approach (hd512 or hd1k) as previously used on the media.
  • +
+

Writing Hard Disk Slices

+

This section covers techniques to copy partial images onto pre-existing +media, in effect performing a selective slice copy. These techniques +currently only apply to hd1k formatted media, which has a partition +table entry, and a convenient 1MB size metric. However adapting to hd512 +is possible, but left to the user.

+

You will need to have access to a Linux/MacOS machine, or have the Linux +tools for Windows installed, including the dd command line tool. For +Windows there are multiple options for installing dd including +MSYS2, CygWin, and +dd for Windows.

+

WARNING: The dd command is a low-level utility that writes +directly to raw disk sectors with almost no safety checks. It is very +easy to corrupt a disk if this tool is used incorrectly.

+

The dd command supports options to define precisely source and +destination offsets and sizes to copy. From the documentation of dd +the following options are important.

+
     if=file  Read input from file instead of the standard input.
+     of=file  Write output to file instead of the standard output.  
+     skip=n   Skip n blocks from the beginning of the input before
+              copying. 
+     seek=n   Seek n blocks from the beginning of the output before
+              copying.
+     count=n  Copy only n input blocks.
+     bs=n     Set both input and output block size to n bytes instead
+              of the default 512
+
+

The best approach is to copy data to the RomWBW partition. To do this, +you must first determine the name that your operating system is using +for the RomWBW disk and partition. An easy way to determine this may be +the linux mount command, which lists the currently mounted partitions. +From here you can more easily determine the naming scheme used by your +operating system.

+

Typically disk devices are named something like /dev/disk9 or +/dev/sdg, noting above the g is a alphabetic and it could be any +letter. This naming is arbitrary and depend on the operating system, and +the specific hardware connecting the device

+

Partitions are typically named by simply adding a number after the name +of the hard disk device. For example, the first partition could be +/dev/disk9s1, /dev/sdg1, or /dev/sdgp1.

+

In the following examples we use the above dd options, noting the +of= option is the RomWBW target partition.

+

** NOTE ** A second approach (Examples 3 and 4) is to address the +hard disk as a raw disk device and we take explicit steps to calculate +the start of the RomWBW partition. While this works, it is better to use +the partition relative approach.

+

The commands in the examples below are run from the Binary folder of +RomWBW distribution.

+

Example 1 : Copy the Games image to an empty slice of our media

+

In this example we will copy the (hd1k) games image to Slice 6 (free) of +our existing media. In this example we assume the media has already been +formatted with the combo image, which already contains 6 slices +(numbered from 0 to 5). We are just copying the needed slice to the +existing media as a new slice (number 6) after the existing slices +making it the 7th slice.

+
Binary % sudo dd if=hd1k_games.img of=/dev/sdg1 seek=6 bs=8M
+
+Password:
+
+1+0 records in
+1+0 records out
+8388608 bytes transferred in 1.917296 secs (4375228 bytes/sec)
+
+

Since bs=8MB the seek=6 skips the first 6 (8MB slices) slices (in the +target image) and writes the games image to the 7th slice.

+

Example 2 : Copy the entire Combo Image without replacing partition table

+

In all of the following examples we use bs=1MB to defines the block +size used in other parameters. This is convenient since the combo image +reserves 1MB for the partition table at the start of the disk.

+

In this example we will copy the (hd1k) combo image (which includes a +partition table) over our media without replacing the partition table. +In this example we assume the media has already been formatted with the +combo image, and we have modified the partition table, which we do not +want to overwrite.

+
Binary % sudo dd if=hd1k_combo.img of=/dev/sdg1 skip=1 bs=1M
+
+Password:
+
+48+0 records in
+48+0 records out
+50331648 bytes transferred in 11.503776 secs (4745528 bytes/sec)
+
+

The skip=1 skips the first 1MB (partition table) in the input file, +effectively stripping out the combo images partition table, before +overwriting the slices in the target partition.

+

Example 3 : Copy the Combo Image without replacing partition table

+

This example is identical to Example 2 except it writes to the target +disk device itself (of=/dev/disk9), not the target partition.

+
Binary % sudo dd if=hd1k_combo.img of=/dev/disk9 skip=1 seek=1 bs=1M
+
+Password:
+
+48+0 records in
+48+0 records out
+50331648 bytes transferred in 11.503776 secs (4745528 bytes/sec)
+
+

The skip=1 skips the first 1MB in the input file, and likewise +seek=1 skips the first 1MB of the target media file we are writing to, +thus in effect we are skipping the first 1MB, which contains the +partition table itself.

+

Example 4 : Copy the Games image to an empty slice of our media

+

In this example we will copy the (hd1k) games image to Slice 6 (free) of +our existing media. In this example we assume the media has already been +formatted with the combo image, which already contains 6 slices +(numbered from 0 to 5) We are just coping the needed slice to this +existing media as a new slice (number 6) after the existing slices +making it the 7th slice.

+
Binary % sudo dd if=hd1k_games.img of=/dev/disk9 seek=49 bs=1M
+
+Password:
+
+8+0 records in
+8+0 records out
+8388608 bytes transferred in 1.917296 secs (4375228 bytes/sec)
+
+

The seek=49 skips the first 49MB of the media file we are writing to. +49 is calculated as (slice number * 8) + 1, where 8 is the size of a +slice and 1 is the size of the partition table im megabytes. Thus we are +skipping 6 slices (in the combo image) and writing to the 7th slice.

+

Operating Systems

+

One of the primary goals of RomWBW is to expose a set of generic +hardware functions that make it easy to adapt operating systems to any +hardware supported by RomWBW. As a result, there are now 8 operating +systems that have been adapted to run under RomWBW. The adaptations are +identical for all hardware supported by RomWBW because RomWBW hides all +hardware specifics from the operating system.

+

By design, the operating systems provided with RomWBW are original and +unmodified from their original distribution. Patches published by the +authors are generally included or applied. The various enhancements +RomWBW provides (such as hard disk slices) are implemented entirely +within the system adaptation component of each operating system (e.g., +CP/M CBIOS). As a result, each operating system should function exactly +as documented by the authors and retain maximum compatibility with +original applications.

+

Note that all of the operating systems included with RomWBW support the +same basic filesystem format from DRI CP/M 2.2 (except for p-System). As +a result, a formatted filesystem will be accessible to any operating +system. The only possible issue is that if you turn on date/time +stamping using the newer OSes, the older OSes will not understand this. +The older OS will not corrupt the files, but the date/time stamps will +not be maintained.

+

The following sections briefly describe the operating system options +currently available and brief operating notes.

+

Digital Research CP/M 2.2

+

This is the most widely used variant of the Digital Research operating +systems. It has the most basic feature set, but is essentially the +compatibility metric for all other CP/M-like operating systems including +those listed below.

+

If you are new to the CP/M world, I would recommend using this CP/M +variant to start with simply because it is the most stable and you are +less likely to encounter compatibility issues.

+

Documentation

+ +

Boot Disk

+

To make a bootable CP/M disk, use the RomWBW SYSCOPY tool to place a +copy of the operating system on the boot track of the disk. The RomWBW +ROM disk has a copy of the boot track call “CPM.SYS”. For example:

+

SYSCOPY C:=B:CPM.SYS

+

Character Device Mapping

+

Character device mapping under CP/M 2.2 has 3 layers:

+

CP/M Logical Device –> CP/M Physical Device –> RomWBW HBIOS Device

+

The CP/M Logical Devices are:

+ + + + + + + + + + + + + + + + + + + + + + + + + +
DeviceDescription
CON:System console device, used by CCP for communication with the operator
RDR:Paper tape reader device
PUN:Paper tape punch device
LST:Output list device
+

The CP/M Physical Devices are:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DeviceDescription
TTY:Teletype device (slow speed console)
CRT:Cathode ray tube device (high speed console)
BAT:Batch processing (input from RDR:, output to LST:)
UC1:User-defined console
PTR:Paper tape reader (high speed reader)
UR1:User-defined reader #1
UR2:User-defined reader #2
PTP:Paper tape punch (high speed punch)
UP1:User-defined punch #1
UP2:User-defined punch #2
LPT:Line printer
UL1:User-defined list device #1
+

CP/M Logical Devices are mapped to CP/M Physical Devices via the IOBYTE +at 0x0003 as shown below.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Logical DeviceLST:PUN:RDR:CON:
IOBYTE Bits7 65 43 21 0
0 (0b00)TTY:TTY:TTY:TTY:
1 (0b01)CRT:PTP:PTR:CRT:
2 (0b10)LPT:UP1:UR1:BAT:
3 (0b11)UL1:UP2:UR2:UC1:
+

The mappings above can be managed using the STAT command. This command +essentially just modifies the IOBYTE value.

+

CP/M Physical Devices are mapped to RomWBW HBIOS devices during the boot +process depending on the number of HBIOS Char devices in the system.

+

All CP/M Physical Devices are initially mapped to HBIOS Char 0. If +additional HBIOS Char devices are available in the system, they will be +mapped as below:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CP/MRomWBW HBIOS
TTY:Char 0
CRT:CRT
BAT:CP/M RDR/LST
UC1:Char 1
PTR:Char 1
UR1:Char 2
UR2:Char 3
PTP:Char 1
UP1:Char 2
UP2:Char 3
LPT:Char 1
UL1:Char 2
+

Normally, the HBIOS Console device (Loader prompt) is on HBIOS Device +Char 0. If it has been reassigned to a different HBIOS character device +before launching CP/M, then the above mapping will be modified. TTY: +will be assigned to the current HBIOS console Char device. The remaining +assignments will be filled in with the other Char devices as available.

+

Notes

+
    +
  • +

    You can change media, but it must be done while at the OS command + prompt and you must warm start CP/M by pressing ctrl-C. This is a + CP/M 2.2 constraint and is well documented in the DRI manual.

    +
  • +
  • +

    SUBMIT.COM has been patched per DRI to always place submit files on + A:. This ensures the submitted file will always be properly executed.

    +
  • +
  • +

    The original versions of DDT, DDTZ, and ZSID used the RST 38 vector + which conflicts with interrupt mode 1 use of this vector. The DDT, + DDTZ, and ZSID applications in RomWBW have been modified to use RST 30 + to avoid this issue.

    +
  • +
  • +

    Z-System applications will not run under CP/M 2.2. For example, the + LDDS date stamper will not work.

    +
  • +
+

Z-System

+

Z-System is the most popular non-DRI CP/M workalike “clone” which is +generally referred to as Z-System. Z-System is intended to be an +enhanced version of CP/M and should run all CP/M 2.2 applications. It is +optimized for the Z80 CPU (as opposed to 8080 for CP/M) and has some +significant improvements such as date/time stamping of files.

+

Z-System is a somewhat ambiguous term because there are multiple +generations of this software. RomWBW Z-System is a combination of both +ZCPR-DJ (the CCP) and ZSDOS 1.1 (the BDOS) when referring to Z-System. +The latest version of Z-System (ZCPR 3.4) is also provided with RomWBW +via the NZ-COM adaptation (see below).

+

Documentation

+ +

Boot Disk

+

To make a bootable Z-System disk, use the RomWBW SYSCOPY tool to place +a copy of the operating system on the boot track of the disk. The RomWBW +ROM disk has a copy of the boot track call “ZSYS.SYS”. For example:

+

SYSCOPY C:=B:ZSYS.SYS

+

Character Device Mapping

+

Mapping of character devices to RomWBW HBIOS Character devices operates +exactly the same as described in Digital Research CP/M +2.2. The CP/M 2.2 STAT command is used to +manipulate the device mappings.

+

Notes

+
    +
  • +

    Although most CP/M 2.2 applications will run under Z-System, some may + not work as expected. The best example is PIP which is not aware of + the ZSDOS paths and will fail in some scenarios (use COPY instead).

    +
  • +
  • +

    Although ZSDOS can recognize a media change in some cases, it will not + always work. You should only change media at a command prompt and be + sure to warm start the OS with a ctrl-C.

    +
  • +
  • +

    ZSDOS has a concept of fast relog of drives. This means that after a + warm start, it avoids the overhead of relogging all the disk drives. + There are times when this causes issues. After using tools like + CLRDIR or MAP, you may need to run “RELOG” to get the drive properly + recognized by ZSDOS.

    +
  • +
  • +

    ZSVSTAMP expects to be running under the ZCPR 3.X command processor. + By default, RomWBW uses ZCPR 1.0 (intentionally, to reduce space + usage) and ZSVSTAMP will just abort in this case. It will work fine if + you implement NZCOM. ZSVSTAMP is included solely to facilitate usage + if/when you install NZCOM.

    +
  • +
  • +

    Many of the tools can be configured (using either ZCNFG or DSCONFIG). + The configuration process modifies the actual application file itself. + This will fail if you try to modify one that is on the ROM disk + because it will not be able to update the image.

    +
  • +
  • +

    DATSWEEP can be configured using DSCONFIG. However, DSCONFIG itself + needs to be configured first for proper terminal emulation by using + SETTERM. So, run SETTERM on DSCONFIG before using DSCONFIG to + configure DATSWEEP!

    +
  • +
  • +

    Generic CP/M PIP and ZSDOS path searching do not mix well if you use + PIP to copy to or from a directory in the ZSDOS search path. Best to + use COPY from the ZSDOS distribution.

    +
  • +
+

NZCOM Automatic Z-System

+

NZCOM is a much further refined version of Z-System (ZCPR 3.4). NZCOM +was sold as an enhancement for existing users of CP/M 2.2 or ZSDOS. For +this reason, (by design) NZCOM does not provide a way to boot directly +from disk. Rather, it is loaded after the system boots into a host OS. +On the RomWBW NZCOM disk images, the boot OS is ZSDOS 1.1. A +PROFILE.SUB file is included which automatically launches NZCOM as +soon as ZSDOS loads.

+

NZCOM is a companion product to Z3PLUS, they are almost identical having +been written by the same team. The only difference is the base operating +system on which they run, but the architecture, the tools, libraries, +files, etc are all primarily the same.

+

NZCOM is highly configurable. The RomWBW distribution has been +configured in the most basic way possible. You should refer to the +documentation and use MKZCM as desired to customize your system.

+

NZCOM has substantially more functionality than CP/M or basic Z-System. +It is important to read the “NZCOM Users Manual.pdf” document in order +to use this operating system effectively.

+

Documentation

+ +

Boot Disk

+

Since NZ-COM boots via Z-System, you can make a bootable NZ-COM disk +using ZSYS.SYS as described in Z-System above. You will +need to add a PROFILE.SUB file to auto-start NZ-COM itself.

+

Character Device Mapping

+

Mapping of character devices to RomWBW HBIOS Character devices operates +exactly the same as described in Digital Research CP/M +2.2. However, it is not possible to +manipulate the CP/M Logical to Physical device mapping using the STAT +command. The mapping is static.

+

Note: A custom ZCPR IOP module could theoretically be used to manage the +character device mappings. RomWBW does not provide this module and +writing an IOP module is beyond the scope of this document.

+

Notes

+
    +
  • +

    All of the notes for Z-System above generally apply to + NZCOM.

    +
  • +
  • +

    There is no DIR command, you must use SDZ instead. If you don’t + like this, look into the ALIAS facility.

    +
  • +
  • +

    For consistency with other ZCPR3 operating systems (ZPM3, Z3PLUS) the + SHOW.COM and HELP.COM command files were renamed to ZSHOW.COM and + ZHELP.COM

    +
  • +
+

Digital Research CP/M 3

+

This is the Digital Research follow-up product to their very popular +CP/M 2.2 operating system. While highly compatible with CP/M 2.2, it +features many enhancements and is not 100% compatible. It makes direct +use of banked memory to increase the user program space (TPA). It also +has a new suite of support tools and help system.

+

Documentation

+ +

Boot Disk

+

To create (or update) a CP/M 3 boot drive, you must place CPMLDR.SYS +on the system track of the disk. You must also place CPM3.SYS and +CCP.COM on the target drive as regular files. Do not place +CPM3.SYS on the boot track. CPMLDR.SYS chain loads CPM3.SYS which +must exist as a regular file on the disk. Subsequently, CPM3.SYS loads +CCP.COM.

+

The CP/M 3 boot files are not included on the ROM disk due to space +constraints. You will need to transfer the following files to your +system from the RomWBW distribution directory Binary/CPM3. You can use +XModem for this (or any of the mechanisms in Transferring +Files.

+
    +
  • CPMLDR.SYS
  • +
  • CPM3.SYS or CPM3BNK.SYS
  • +
  • CCP.COM
  • +
+

The CPM3.SYS boot file is provided in 2 versions. In the Binary/CPM3 +distribution directory, CPM3.SYS is the “non-banked” version of CP/M +3. The CPM3BNK.SYS file is the “banked” version of CP/M 3. You almost +certainly want to transfer the banked CPM3BNK.SYS version.

+

After transferring the boot files to your RomWBW system, you will need +to use SYSCOPY to place CPMLDR.SYS on the boot track of the target +drive. CPM3.SYS and CCP.COM can be copied to the target drive using +any standard file copy tool such as PIP or COPY.

+

You do not need to be booted into CP/M 3 to create or update a CP/M 3 +disk. The recommended approach is to boot CP/M 2.2 or Z-System from ROM. +Transfer the boot files to the RAM disk. Then simply copy the files onto +the CP/M 3 disk. Assuming the target CP/M 3 disk is F:, you can use the +following commands to place the files on the target drive:

+
SYSCOPY F:=A:CPMLDR.SYS
+COPY A:CPM3BNK.SYS F:CPM3.SYS
+COPY A:CCP.COM F:
+
+

Note in the example above that CPM3BNK.SYS is renamed to CPM3.SYS in +the copy command.

+

Character Device Mapping

+

Character device mapping under CP/M 3 has 3 layers:

+

CP/M Logical Device –> CP/M Physical Device –> RomWBW HBIOS Device

+

The primary CP/M Logical Devices are:

+ + + + + + + + + + + + + + + + + + + + + +
DeviceDescription
CON:Console input or output device
AUX:Auxiliary Input or Output Device
LST:List output device, usually the printer
+

There are various aliases for these devices. Please refer to the CP/M 3 +Users Guide for more information.

+

The mapping of CP/M 3 Logical Devices to Physical Devices is performed +using the DEVICE command.

+

CP/M 3 refers to Physical Character Devices using the COM device +label. These COM devices are mapped directly to the RomWBW HBIOS Char +devices as described below:

+

COM0: –> HBIOS Char 0
+COM1: –> HBIOS Char 1
+COM2: –> HBIOS Char 2
+      . . .
+COMn: –> HBIOS Char n

+

Notes

+
    +
  • +

    The COPYSYS command described in the DRI CP/M 3 documentation is not + provided with RomWBW. The RomWBW SYSCOPY command is used instead.

    +
  • +
  • +

    Although CP/M 3 is generally able to run CP/M 2.2 programs, this is + not universally true. This is especially true of the utility programs + included with the operating system. For example, the SUBMIT program + of CP/M 3 is completely different/incompatible from the SUBMIT + program of CP/M 2.2.

    +
  • +
  • +

    RomWBW fully supports CP/M 3 file date/time stamping, but this + requires that the disk be properly initialized for it. This process + has not been performed on the CP/M 3 disk image. Follow the CP/M 3 + documentation to complete this process, if desired.

    +
  • +
+

Z3PLUS Z-System for CP/M-Plus

+

Z3PLUS is a much further refined version of Z-System (ZCPR 3.4). Z3PLUS +was sold as an enhancement for existing users of CP/M 3. For this +reason, (by design) Z3PLUS does not provide a way to boot directly from +disk. Rather, it is loaded after the system boots into CP/M 3. A +PROFILE.SUB file is included which automatically launches Z3PLUS as +soon as CP/M 3 loads.

+

Z3PLUS is a companion product to NZ-COM, they are almost identical +having been written by the same team. The only difference is the base +operating system on which they run, but the architecture, the tools, +libraries, files, etc are all primarily the same.

+

Z3PLUS is highly configurable. The RomWBW distribution has been +configured in the most basic way possible. You should refer to the +documentation to customize your system.

+

Z3PLUS has substantially more functionality than CP/M 3 or the basic +Z-System. It is important to read the “Z3PLUS Users Manual.pdf” document +in order to use this operating system effectively.

+

Documentation

+ +

Boot Disk

+

Since Z3PLUS boots via CP/M 3, you first must make the disk CP/M 3 +bootable. This is not a simple process, as well as placing CPMLDR.SYS +on the system track of the disk there are several files that are +required on the disk itself.This is described in Digital Research CP/M +3 section above.

+

You will need to add a PROFILE.SUB file to auto-start Z3PLUS itself.

+

Character Device Mapping

+

Mapping of character devices to RomWBW HBIOS Character devices operates +exactly the same as described in Digital Research CP/M +3. The CP/M 3 DEVICE command is used to +manipulate the device mappings.

+

Notes

+
    +
  • +

    All of the notes for Digital Research CP/M + 3 above generally apply to Z3PLUS.

    +
  • +
  • +

    Some applications in the Z3PLUS distribution have been upgraded with + newer versions. This is done with in

    +
  • +
+

ZPM3

+

Simeon Cran’s ZPM3 is an interesting combination of the features of both +CP/M 3 and ZCPR3. Essentially, it has the features of and compatibility +with both.

+

Due to this dual compatibility, the ZPM3 distribution image contains +most of the standard CP/M 3 files as well as a variety of common ZCPR3 +applications. However, you will notice that user area 0 of the disk has +only a few files. Most of the files are distributed among other user +areas which is standard practice for ZCPR3. Most importantly, you will +see most of the applications in user area 15. The applications can be +executed from any user area because ZPM3 has a default search path that +includes User 15.

+

The ZPM3 distribution comes with essentially no utility programs at all. +In addition to the standard CP/M 3 utilities, RomWBW includes a variety +of common ZCPR3 utilities.

+

Documentation

+

ZPM3 has no real documentation. You are expected to understand both CP/M +3 and ZCPR 3. The best source of information is:

+ +

Boot Disk

+

To create (or update) a ZPM3 boot drive, you must place ZPMLDR.SYS on +the system track of the disk. You must also place CPM3.SYS, +ZCCP.COM, ZINSTAL.ZPM, and STARTZPM.COM on the target drive as +regular files. Do not place CPM3.SYS on the boot track. ZPMLDR.SYS +chain loads CPM3.SYS which must exist as a regular file on the disk. +Subsequently, CPM3.SYS loads CCP.COM.

+

The CP/M 3 boot files are not included on the ROM disk due to space +constraints. You will need to transfer the following files to your +system from the RomWBW distribution directory Binary/ZPM3. You can use +XModem for this (or any of the mechanisms in Transferring +Files.

+
    +
  • ZPMLDR.SYS
  • +
  • CPM3.SYS
  • +
  • ZCCP.COM
  • +
  • ZINSTAL.ZPM
  • +
  • STARTZPM.COM
  • +
+

You may be surprised to see the file called CPM3.SYS. This is not a +typo. Although it is called CPM3.SYS, it is ZPM and not the same as +CPM3.SYS in the CPM3 directory. Also, unlike CP/M 3, ZPM3 is always +banked, so you will not find two versions of the file. CPM3.SYS is a +banked implementation of ZPM3.

+

After transferring the boot files to your RomWBW system, you will need +to use SYSCOPY to place ZPMLDR.SYS on the boot track of the target +drive. The remaining boot files can be copied to the target drive using +any standard file copy tool such as PIP or COPY.

+

You do not need to be booted into ZPM3 to create or update a ZPM3 disk. +The recommended approach is to boot CP/M 2.2 or Z-System from ROM. +Transfer the boot files to the RAM disk. Then simply copy the files onto +the ZPM disk. Assuming the target ZPM3 disk is F:, you can use the +following commands to place the files on the target drive:

+
SYSCOPY F:=A:ZPMLDR.SYS
+COPY A:CPM3.SYS F:CPM3.SYS
+COPY A:CCP.COM F:
+COPY A:ZINSTAL.ZPM F:
+COPY A:STARTZPM.COM F:
+
+

Character Device Mapping

+

Mapping of character devices to RomWBW HBIOS Character devices operates +exactly the same as described in Digital Research CP/M +3. The CP/M 3 DEVICE command is used to +manipulate the device mappings.

+

Notes

+
    +
  • +

    The ZPM3 operating system is contained in the file called CPM3.SYS + which is confusing, but this is as intended by the ZPM3 distribution. + I believe it was done this way to make it easier for users to + transition from CP/M 3 to ZPM3.

    +
  • +
  • +

    The command line editing key bindings were slightly modified by Jon + Saxton when he applied a few ZPM3 fixes. This is explained in the file + zpm3fix.txt in the distribution folder Source/ZPM3. The current key + bindings are from the “New” column below.

    +
  • +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OldNewFunction
^A^Aone word left
^B^Bto beginning/end of line
^C^Creboot if at start of line
^D^Dright one char
^E^Eget previous line
^F^Fright one word
^G^Gdelete char at cursor
^H^Hdestructive backspace
^I^I(TAB) ignored here
^J^J(LF) exit editor
^K^Kdelete all to the right
^L^Lignored
^M^M(CR) exit editor
^N^Nignored
^O^Oignored
^P^Ptoggle printer echoing
^Q^Qtoggle autoprompt (if enabled)
^R^Rignored
^S^Sleft one char
^T^Tdelete word at cursor
^U^Uadd line to history
^V^Vclear line, delete from history
^W^Xget next line from history
^X^Wdelete all to the left
^Y^Yclear line
+

QP/M

+

QP/M is another OS providing compatibility with and enhancements to CP/M +2.2. It is provided as a bootable disk image for RomWBW.

+

Refer to the ReadMe.txt file in Source/Images/d_qpm for more details +regarding the RomWBW adaptation and customizations.

+

Documentation

+ +

Boot Disk

+

To create or update a bootable QP/M Z-System disk, a special process is +required. QP/M is not provided in source format. You are expected to +install QP/M over an existing CP/M installation using the QINSTALL.COM +application.

+

To update an existing QP/M boot disk with the latest RomWBW CBIOS, you +must use 2 steps: apply the generic CP/M system track, then reinstall +the QP/M components. To do this, you can perform the following steps:

+
    +
  1. +

    Boot to the existing QP/M disk. At this point, drive A should be the + QP/M disk that you wish to update. You may receive a warning about + CBIOS/HBIOS version mismatch.

    +
  2. +
  3. +

    Use RomWBW SYSCOPY to place the stock RomWBW CP/M OS image onto + the system tracks of the QP/M boot disk:

    +

    SYSCOPY A:=x:CPM.SYS

    +

    where x is the drive letter of your ROM Disk.

    +
  4. +
  5. +

    Run QINSTALL to overlay the QP/M OS components on your QP/M boot + disk.

    +
  6. +
+

WARNING: QINSTALL has no mechanism for retaining previous +non-default settings. Any previous non-default settings you previously +made with QINSTALL will need to be reapplied. The pre-built RomWBW +QP/M disk image includes a couple of specific non-default settings to +optimize use with RomWBW. Please review the notes in the ReadMe.txt file +in Source/Images/d_qpm.

+

Character Device Mapping

+

Mapping of character devices to RomWBW HBIOS Character devices operates +exactly the same as described in Digital Research CP/M +2.2. The mappings can be viewed or modified +using the QP/M QSTAT command which is analogous to the CP/M 2.2 STAT +command. Do not use the CP/M 2.2 STAT command under QP/M.

+

Notes

+
    +
  • +

    QPM is not available as source. This implementation was based on the + QPM binary distribution and has been minimally customized for RomWBW.

    +
  • +
  • +

    When booted, the QPM startup banner will indicate CP/M 2.2. This is + because QPM uses the CP/M 2.2 CBIOS code.

    +
  • +
  • +

    QINSTALL is used to customize QPM. It is included on the disk image. + You should review the notes in the ReadMe.txt file in + Source/Images/d_qpm before making changes.

    +
  • +
  • +

    In addition to the QPM disk image, all of the QPM distribution files + can be found in the RomWBW distribution in the Source/Images/d_qpm/u0 + directory.

    +
  • +
  • +

    The QPM disk image is not included as one of the slices on the RomWBW + Combo Disk Image. If you want to include QPM, you can do so by + following the directions in Source/Images/Readme.txt.

    +
  • +
+

UCSD p-System

+

This is a full implementation of the UCSD p-System IV.0 for Z80 running +under RomWBW. Unlike the OSes above, p-System uses its own unique +filesystem and is not interoperable with other OSes.

+

It was derived from the p-System Adaptable Z80 System. Unlike some other +distributions, this implements a native p-System Z80 Extended BIOS, it +does not rely on a CP/M BIOS layer.

+

The p-System is provided on a hard disk image file called psys.img. This +must be copied to its own dedicated hard disk media (CF Card, SD Card, +etc.). It is booted by selecting slice 0 of the corresponding hard disk +unit at the RomWBW Boot Loader prompt. Do not attempt to use CP/M slices +on the same disk.

+

Due to limitations in the p-System configuration mechanism, it does not +recognize the arrow keys of an ANSI Terminal. To work around this, the +following control keys have been defined:

+ + + + + + + + + + + + + + + + + + + + + + + + + +
FunctionKey
Upctrl+E
Downctrl+X
Leftctrl+S
Rightctrl+D
+

Refer to +Source/pSys/ReadMe.txt +for more details about the p-System adaptation.

+

Documentation

+ +

Boot Disk

+

There is no mechanism provided to create a p-System boot disk from +scratch under RomWBW. This has already been done as part of the porting +process. You must use the provided p-System hard disk image file which +is bootable.

+

Character Device Mapping

+

RomWBW Character Devices are automatically assigned to p-System devices +at startup. The current HBIOS Console device is assigned to CONSOLE:.
+The next available HBIOS Char device is assigned to REMIN:/REMOUT:. The +next available HBIOS Char devices is assigned to PRINTER:

+

Notes

+
    +
  • +

    There is no floppy support at this time.

    +
  • +
  • +

    The hard disk image contains 6 p-System slices which are assigned to + p-System unit numbers 4, 5, 9, 10, 11, and 12 which is standard for + p-System. Slices 0-5 are assigned sequentially to these p-System unit + numbers and it is not possible to reassign them. Unit #4 (slice 0) is + bootable and contains all of the p-System distribution files. Unit #5 + (slice 1) is just a blank p-System filesystem. The other units (9-12) + have not been initialized, but this can be done from Filer using the + Zero command.

    +
  • +
  • +

    p-System relies heavily on the use of a full screen terminal. This + implementation has been setup to expect an ANSI or DEC VT-100 terminal + or emulator. The screen output will be garbled if no such terminal or + emulator is used for console output.

    +
  • +
  • +

    There is no built-in mechanism to move files in and out of p-System. + However, the .vol files in Source/pSys can be read and modified by + CiderPress. CiderPress is able to add and remove individual files.

    +
  • +
+

Andrew Davidson has created a Python script that can extract p-System + volumes from an existing disk image file. The script is also capable + of inserting a modified volume back into the disk image file. This + tool is available at https://github.com/robosnacks/psysimg.

+

FreeRTOS

+

Phillip Stevens has ported FreeRTOS to run under RomWBW. FreeRTOS is not +provided in the RomWBW distribution. FreeRTOS is available under the +MIT licence and further general +information is available at +FreeRTOS.

+

Phillip may be contacted via his GitHub +Page.

+

Fuzix

+

Fuzix is a Unix-ish operating system for small systems. It is the work +of Alan Cox and is hosted on GitHub at +https://github.com/EtchedPixels/FUZIX. Fuzix itself is a stand-alone +operating system, but it frequently utilizes RomWBW to boot and launch +on RomWBW-supported platforms.

+

For those Fuzix platforms that leverage RomWBW for startup, you will +program your ROM with the normal RomWBW ROM – there is no Fuzix-specific +ROM. A Fuzix disk image for your system is then written to your disk +media. After booting your system via the normal RomWBW ROM, you start +Fuzix simply by choosing the disk device containing the Fuzix image at +the RomWBW Loader prompt.

+

To create a Fuzix disk image:

+
    +
  • +

    Locate and download the Fuzix disk image for your system from + https://www.fuzix.org/. For each platform, you will typically find + two image files. An emulator image (emu-xxx.img) and a disk image + (disk.img). You want the disk image file.

    +
  • +
  • +

    Write the disk image file to your physical media (CF Card, SD Card, + etc.) starting at the beginning of the media (first sector). Do not + combine the Fuzix image with the RomWBW disk images – they are + entirely separate.

    +
  • +
+

To boot into Fuzix:

+
    +
  • +

    Insert your Fuzix disk media.

    +
  • +
  • +

    Power-up or reset your system. RomWBW should load normally and bring + you to the RomWBW Boot Loader prompt.

    +
  • +
  • +

    Depending on the platform, Fuzix may be built to run at a different + baud rate that the default RomWBW baud rate. If so, it is best to + change your RomWBW baud rate prior to initiating the Fuzix startup. + You can do this at the loader prompt with a command like this:

    +
  • +
+

I 0 38400

+

Replace 38400 with the desired baud rate for Fuzix. You will be + prompted to change your terminal’s baud rate at this time.

+
    +
  • +

    At the RomWBW Boot Loader prompt, enter the disk unit number of the + Fuzix media. Fuzix should load and you will see device + discovery/information messages that vary depending on your platform. + This is a typical example:

    +

    RCBus [RCZ180_nat_wbw] Boot Loader + FP Switches = 0x00

    +

    Boot [H=Help]: 2

    +

    Booting Disk Unit 2, Slice 0, Sector 0x00000000...

    +

    Volume "Fuzix 126 Loader" [0xF200-0xF400, entry @ 0xF200]... + FUZIX version 0.4 + Copyright (c) 1988-2002 by H.F.Bower, D.Braun, S.Nitschke, H.Peraza + Copyright (c) 1997-2001 by Arcady Schekochikhin, Adriano C. R. da Cunha + Copyright (c) 2013-2015 Will Sowerbutts wi...@sowerbutts.com + Copyright (c) 2014-2023 Alan Cox al...@etchedpixels.co.uk + Devboot + 512kB total RAM, 448kB available to processes (15 processes max) + Enabling interrupts ... ok. + 0000 : CF Card - OK + 0001 : - absent + hda: hda1 hda2 (swap) + bootdev:

    +
  • +
  • +

    At the bootdev: prompt, enter hda1. Fuzix should load and you will + be prompted for a date/time. Here is a typical example:

    +

    bootdev: hda1 + Mounting root fs (root_dev=1, ro): OK + Starting /init + init version 0.9.1 + Checking root file system. + Current date is Fri 2023-08-18 + Enter new date: + Current time is 13:30:24 + Enter new time:

    +

    ^ ^ + n n Fuzix 0.4

    +
    +

    @< + Welcome to Fuzix + m m

    +
    +

    login:

    +
  • +
  • +

    At the login: prompt, enter root. No password is required. You + should then get a Fuzix # command prompt.

    +

    login: root

    +

    Welcome to FUZIX. + #

    +
  • +
+

You may now use Fuzix as desired. The general operation and use of Fuzix +is outside of the scope of this document.

+

Custom Applications

+

The operation of the RomWBW hosted operating systems is enhanced through +several custom applications. You have already read about one of these – +the ASSIGN command. These applications are functional on all of the OS +variants included with RomWBW.

+

The applications discussed here are not the same as the built-in ROM +applications mentioned previously. These applications run as commands +within the operating systems provided by RomWBW. So, these commands are +only available at an operating system prompt after an operating system +has been loaded.

+

All of the RomWBW Custom Applications are built to function under all of +the RomWBW Operating Systems (except for p-System). In general, the +applications will automatically adapt as needed to the currently running +operating system. One exception is FDU – the Floppy Disk Utility. This +application requires that you pick the floppy disk interface you want to +interact with.

+

There is more complete documentation of all of these applications in the +related RomWBW manual “RomWBW +Applications” +found in the Doc directory of the distribution.

+

The following custom applications are found on the ROM disk and are, +therefore, globally available.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Application**Description
ASSIGNAdd, change, and delete drive letter assignments. Use ASSIGN /? for usage instructions.
SYSCOPYCopy system image to a device to make it bootable. Use SYSCOPY with no parms for usage instructions.
MODEReconfigures serial ports dynamically.
FDUFormat and test floppy disks. Menu driven interface.
FORMATWill someday be a command line tool to format floppy disks. Currently does nothing!
XMXModem file transfer program adapted to hardware. Automatically uses primary serial port on system.
FLASHWill Sowerbutts’ in-situ ROM programming utility.
FDISK80John Coffman’s Z80 hard disk partitioning tool. See documentation in Doc directory.
FATAccess MS-DOS FAT filesystems from RomWBW (based on FatFs).
TALKDirect console I/O to a specified character device.
RTCManage and test the Real Time Clock hardware.
TIMERDisplay value of running periodic system timer.
CPUSPDChange the running CPU speed and wait states of the system.
+

Some custom applications do not fit on the ROM disk. They are found on +the disk image files or the individual files can be found in the +Binary/Apps directory of the distribution. They are also included on the +floppy disk and hard disk images.

+ + + + + + + + + + + + + + + + + +
ApplicationDescription
TUNEPlay .PT2, .PT3, .MYM audio files.
INTTESTTest interrupt vector hooking.
+

Real Time Clock & Date/Time Stamping

+

RomWBW supports a variety of real time clock hardware. If your system +has this hardware, then it will be able to maintain the current date and +time even while your system is turned off.

+

Additionally, depending on the operating system being used, you may be +able to utilize date/time stamping of files. To facilitate this a CP/M +clock driver (WBWCLK) has been included inside CLOCKS.DAT that will +read the clock via a RomWBW HBIOS call

+

You can determine if your system has a real time clock present (and +functioning) by looking at the boot messages. Here is an example of a +boot message reflecting the detection of a valid real time clock module:

+

DSRTC: MODE=STD IO=0x8A Thu 2023-10-19 14:07:11 CHARGE=ON

+

This example is from a DSRTC clock module. You may have a different one, +but it will always display the current date/time.

+

In some cases, your real time clock will support charging of the battery +or super-capacitor while the system has power. The status of this +charging is displayed.

+

If the date/time of your RTC needs to be updated, you will need to do +this with one of the utilities described below. There is no ability to +update the date/time of the RTC in the RomWBW Boot Loader or Monitor.

+

Date/Time Utilities

+

RomwWBW includes two utilities for displaying or setting the date/time +stored by the RTC. They are both a bit different and are briefly +described below.

+

A third utility TESTCLOK is also included as part of ZSDOS

+

WDATE Utility

+

The WDATE utility (contributed by Kevin Boone) is an application that +will display and/or update the current date/time. Its operation is +described in RomWBW +Applications. +This utility works with any of the supported RomWBW RTC hardware. Here +is an example of displaying and updating the date/time with this +utility:

+
A>wdate
+Thursday 19 October 14:14:43 2023
+
+A>wdate 23 10 19 14 24 30
+
+A>wdate
+Thursday 19 October 14:24:34 2023
+
+

Note that WDATE does not have anything to do with date/time stamping +of files. It merely displays and sets the real time clock value.

+

RTC Utility

+

Like WDATE, the RTC utility (contributed by Andrew Lynch) will let +you display and set the current date/time. However, this utility only +works with the DSRTC hardware (DS1302 chip). It is a “direct to hardware +application”. Its operation is described in RomWBW +Applications. +Here is an example of displaying and updatting the date/time with this +utility:

+
A>rtc
+Start RTC Program
+RomWBW HBIOS, Mark 4 RTC Latch Port 0x8A
+
+RTC: Version 1.9
+Commands: E)xit T)ime st(A)rt S)et R)aw L)oop C)harge N)ocharge D)elay I)nit G)et P)ut B)oot W)arm-start H)elp
+
+RTC>t
+Current time: 23-10-19 14:30:25-05
+
+RTC>i
+Init date/time.
+
+YEAR:23
+MONTH:10
+DATE:19
+HOURS:14
+MINUTES:31
+SECONDS:00
+DAY:05
+
+

The RTC utility is also capable of turning the charging feature of the +DS1320 chip on or off. Here is an example of turning if off and back on:

+
A>rtc
+Start RTC Program
+RomWBW HBIOS, Mark 4 RTC Latch Port 0x8A
+
+
+RTC: Version 1.9
+Commands: E)xit T)ime st(A)rt S)et R)aw L)oop C)harge N)ocharge D)elay I)nit G)et P)ut B)oot W)arm-start H)elp
+
+RTC>n
+Trickle charger disabled.
+
+RTC>c
+Trickle charger enabled.
+
+

Do not enable charging unless you are sure that your system supports +this. If your RTC is being powered by a normal battery, it would be +dangerous to enable charging.

+

TESTCLOK Utility

+

The TESTCLOK utility is used to test a selected CPM clock driver +loaded from the CLOCKS.DAT file. After selecting the location of +CLOCKS.DAT and the clock driver (45. WBWCLK) it displays the currently +configured time until a key is pressed.

+
A>testclok
+
+TESTCLOK V1.0    Copyright (C) 1988    H.F. Bower / C.W. Cotrill
+
+Extract Clock from Library ([Y]/N) : Y
+Location of CLOCKS.DAT [A0:] : <RETURN>
+
+  1. ACTRIX             2. ALSPA              3. AMPRO-LB         
+  4. ANLYTCL-PRD        5. AP2-CDZ180         6. AP2-THND/MT      
+  7. AP2-TIMASTR        8. AP2E+PCP-TM        9. AP2E+PCPI        
+ 10. AP2E-THUNDR       11. AP2E-TMASTR       12. BIG-BD-II        
+ 13. BP-BIOS           14. CCS-WALLCLK       15. CPUPRO-SSB1      
+ 16. ELECTR-MFIO       17. EPSON-QX10        18. ETS180IO+        
+ 19. H19-SUPER19       20. H19-ULTRA         21. H19-WATZMAN      
+ 22. H89-BITZERO       23. H89-PC12          24. H89-WIDGET       
+ 25. H89-WISE          26. H89UTI            27. HEATH-BIOS       
+ 28. HOUSEMASTER       29. K83-HOLMES        30. KAYPRO-84        
+ 31. KENMOR-ZTIM       32. KPRO-ADVENT       33. KPRO-LEGACY      
+ 34. MD3-MACK          35. MTN100K-DAY       36. ONEAC-ON!        
+ 37. OTRANA-ATCH       38. P&T-HEARTBT       39. QTSYS-S100       
+ 40. RELATIVE          41. S100-5832         42. SB180-HRTBT      
+ 43. SB180-XBIOS       44. SIMHCLOK          45. WBWCLK           
+ 46. XEROX-820         47. ZSDOS-BIOS
+
+Enter Clock Driver Selection : 45
+
+..Loading : WBWCLK      ... 
+Linking Clock Module... OK
+RomWBW HBIOS Clock      1.1
+
+RomWBW Series HBIOS Clock
+
+Press any key to quit...
+
+ 19 Oct 2023  14:24:34
+
+

Since this runs at the CPM driver level it is useful as an end-to-end +test to prove that date time stamping is able to read the correct time

+

The TESTCLOK utility is provided by ZSDOS, plese see the ZSDOS Manual +for further information

+

Date/Time File Stamping

+

If an RTC is available in your system, then most operating systems can +use it to date/time stamp files. This just means recording the date/time +of file creation, update, and or access in the directory. This +capability is available in all of the RomWBW operating system except the +original DRI CP/M 2.2.

+

Three types of date/time stamping are supported using realtime clock +supported by RomWBW HBIOS. DateStamper, NZT and P2DOS.

+

In some cases (such as ZSDOS), you must load an RSX (memory resident +utility) to enable date/time stamping of files. This could be automated +using a PROFILE.SUB file. Preconfigured loaders are provided, +bypassing the need to use SETUPZST.

+

Additionally, you will need to initialize the directory. The procedure +varies depending on the date/time stamping mechanism, so you must review +the associated documentation.

+

The date/time stamping mechanisms for each operating system are +generally not compatible. If you initialize a directory for a type of +stamping, you should be careful not to manipulate that directory with a +different operating system with a different date/time stamping +mechanism. Doing so may corrupt the directory.

+

The RomWBW disk images do not have date/time stamping initialized. This +is to avoid any chance of directory corruption.

+

DateStamper

+

DateStamper datestamping follows the standard set by Plu*Perfect +Systems. This method stores stamps in a disk file named !!!TIME&.DAT. +Only DateStamper stamping stores full time and date stamps for file +Creation, Last Modification, and Last Access, and may be used with any +CP/M diskette format. In addition, the DateStamper protocol is supported +by a mature set of compatible utilities.

+

Key Utilities

+
    +
  • LDDS.COM - Load DateStamper date/time stamping resident extension. + (RomWBW Provided)
  • +
  • PUTDS.COM - Prepare disk for DateStamper date/time stamping.
  • +
+

After using PUTDS to initialize a directory for ZDS date stamping, it +may be necessary to run RELOG before the stamping routines will actually +start working.

+

P2DOS (CP/M Plus compatible)

+

CP/M Plus-type datestamping is also widely used due to the popularity of +CP/M Plus (also know as CP/M 3). CP/M Plus-type file datestamping uses +directory sectors to store file datestamps which may be accessed more +quickly by programs, but there is no Last File Access stamp. Finally, +the range of utilities for this type of stamps is more limited than for +the DateStamper protocol.

+

Key Utilities

+
    +
  • LDP2D.COM - Load P2DOS date/time stamping resident extension. (RomWBW + Provided)
  • +
  • INITDIR.COM - Prepares disks for P2DOS-type file stamping.
  • +
+

NZT

+

The use of NZT needs to be further documented

+

Key Utilities

+
    +
  • LDNZT.COM - Load NZT date/time stamping resident extension. (RomWBW + Provided)
  • +
+

Additional Notes

+

The following files have been provided, customised and tested for for +use in RomWBW

+
    +
  • CLOCKS.DAT - Library of clock drivers, which has been updated to + include the RomWBW clock driver WBWCLK, and also includes the SIMHCLOK + clock driver. The file is just a standard LU type library and is + easily updated using NULU. The members are the relocatable binaries, + but with the .REL extension removed.
  • +
  • STAMPS.DAT - Library of available date/time stamping modules for + SETUPZST. The file has been replaced with an updated version from the + Walnut Creek CP/M CDROM. The original version has a bug that prevents + RSX (resident system extension) mode to load properly.
  • +
+

Additional Notes

+
    +
  • SETUPZST (provided by ZSDOS) Should not normally be needed since the + creation of the appropriate LDTIM loaders has already been performed.
  • +
  • FILEDATE only works with DateStamper style date stamping. If you run + it on a drive that is not initialized for DateStamper, it will + complain FILEDATE, !!!TIME&.DAT missing. This is normal and just + means that you have not initialized that drive for DateStamper (using + PUTDS).
  • +
  • ZXD will handle either DateStamper or P2DOS type date stamping. + However, it must be configured appropriately. As distributed, it + will look for P2DOS date stamps. Use ZCNFG to reconfigure it for P2DOS + if that is what you are using.
  • +
+

Timezone

+

None of the operating systems distributed with RomWBW have any concept +of timezone. When files are date/time stamped, the date/time will simply +be whatever date/time the RTC currently has.

+

The normal practice is to set the RTC to your local time. This implies +that you would need to manually adjust the RTC for daylight savings time +and/or when you travel to a different time zone.

+

The date/time stamps of files in directories will also be stored in +local time. This includes files stored in a FAT filesystem. If you +subsequently view the directory from modern machines (Windows, Linux, +etc.), the date/time displayed will depend on the behavior of the modern +system.

+

For example, Linux assumes that the date/time of files is UTC. So, if +you create a file on a FAT filesystem with your RomWBW computer and then +use Linux to view the directory, the date/time stamps will seem “off” by +a few hours.

+

The only alternative you may consider is setting the date/time of your +RTC to UTC. Since UTC is consistent across all timezones and daylight +savings time, your file date/time stamps will also be consistent. Of +course, this will mean that your RomWBW computer will display a +date/time that seems wrong because it is not local time.

+

CP/NET Networking

+

Digital Research created a simple network file sharing system called +CP/NET. This allowed a network server running CP/NOS to host files +available to network attached CP/M computers. Essentially, the host +becomes a simple file sharing server.

+

RomWBW disk images include an adaptation of the DRI CP/NET client +software provided by Douglas Miller. RomWBW does not support operation +as a network server itself. However, Douglas has also developed a +Java-based implementation of the DRI network server that can be used to +provide host services from a modern computer.

+

Both CP/NET 1.2 and 3.0 clients are provided. Version 1.2 is for use +with CP/M 2.2 and compatible OSes. Version 3.0 is for use with CP/M 3 +and compatible OSes.

+

The CP/NET client software provided with RomWBW requires a supported +ethernet interface module. At this time, the following are supported:

+
    +
  • RCBus MT011 w/ Ethernet Featherwing and (optionally) SPI FRAM (e.g., + Adafruit SPI Non-Volatile FRAM Breakout)
  • +
  • Duodyne Disk I/O w/ Wiz850IO and (optionally) SPI NVRAM (e.g., + 25LC256)
  • +
  • Generic Serial Interface
  • +
+

NOTE: The Generic Serial Interface is supported by RomWBW, but is +not documented here. You must refer to the CP/NET documentation +referenced below.

+

The client software interacts directly with this hardware. In a future +version of RomWBW, I hope to add a generic networking API that will +allow a greater range of network hardware to be used.

+

To use CP/NET effectively, you will want to review the documentation +provided by Douglas on at his cpnet-z80 GitHub +Project. Additionally, you +should consult the DRI documentation which is not included with RomWBW, +but is available on the +cpnet-z80 site.

+

Below, I will provide the general steps involved in setting up a network +using MT011 with RomWBW.

+

CP/NET Client Setup

+

The CP/NET client files are included on the RomWBW disk images, but they +are found in user area 4. They are placed there to avoid confusing +anyone that is not specifically trying to run a network client. They are +only found on the CPM 2.2 and CP/M 3 slices. Using CP/NET on alternative +OSes may work, but is not officially supported.

+

The CP/NET client files are packaged in .LBR library files. The +library files are found in user area 4.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileCP/NET VersionOSHardware
CPN12MT.LBRCP/NET 1.2CP/M 2.2RCBus w/ MT011
CPN3MT.LBRCP/NET 3CP/M 3RCBus w/ MT011
CPN12DUO.LBRCP/NET 1.2CP/M 2.2Duodyne w/ Disk I/O
CPN3DUO.LBRCP/NET 3CP/M 3Duodyne w/ Disk I/O
CPN12SER.LBRCP/NET 1.2CP/M 2.2RomWBW Serial Port
CPN3SER.LBRCP/NET 3CP/M 3RomWBW Serial Port
+

First, you need to merge the files from the correct library file into +user area 0. This is done by extracting the files using the NULU +library management utility application.

+
    +
  1. +

    Start NULU specifying desired CP/NET library for \<filename>:

    +

    A>NULU 4:<filename>

    +
  2. +
  3. +

    At the NULU prompt, extract the files using the -E *.* command:

    +

    -READY A0:>-E *.*

    +
  4. +
  5. +

    Exit NULU using the -X command:

    +

    -Extract members A0:>-x

    +
  6. +
+

Here is an example of extracting the CP/NET 1.2 client files for an +RCBus system w/ MT011. You should be in user area 0 when performing this +operation.

+
A>nulu 4:cpn12mt
+NULU 1.52  (07/12/87)
+Copyright (C) 1984, 1985 & 1987 by Martin Murray
+Bug fixes in version 1.52 by Mick Waters
+
+TYPE -H FOR HELP
+
+Library A4:CPN12MT.LBR open.
+(Buffer size: 259 sectors)
+Active entries: 27, Deleted: 0, Free: 5, Total: 32.
+-READY A0:>-e *.*
+Extracting...
+  CCP     .SPR to A0:CCP     .SPR
+  CPM2NET .HLP to A0:CPM2NET .HLP
+  CPNBOOT .COM to A0:CPNBOOT .COM
+  CPNET12 .HLP to A0:CPNET12 .HLP
+  CPNETLDR.COM to A0:CPNETLDR.COM
+  CPNETSTS.COM to A0:CPNETSTS.COM
+  DSKRESET.COM to A0:DSKRESET.COM
+  ENDLIST .COM to A0:ENDLIST .COM
+  LOCAL   .COM to A0:LOCAL   .COM
+  LOGIN   .COM to A0:LOGIN   .COM
+  LOGOFF  .COM to A0:LOGOFF  .COM
+  MAIL    .COM to A0:MAIL    .COM
+  NDOS    .SPR to A0:NDOS    .SPR
+  NETDOWN .COM to A0:NETDOWN .COM
+  NETSTAT .COM to A0:NETSTAT .COM
+  NETWORK .COM to A0:NETWORK .COM
+  NVRAM   .COM to A0:NVRAM   .COM
+  PIPNET  .COM to A0:PIPNET  .COM
+  RDATE   .COM to A0:RDATE   .COM
+  SNIOS   .SPR to A0:SNIOS   .SPR
+  SRVSTAT .COM to A0:SRVSTAT .COM
+  TR      .COM to A0:TR      .COM
+  WIZCFG  .COM to A0:WIZCFG  .COM
+  WIZDBG  .COM to A0:WIZDBG  .COM
+  WIZTEST .COM to A0:WIZTEST .COM
+  XSUBNET .COM to A0:XSUBNET .COM
+-Extract members A0:>-x
+
+Closing A4:CPN12MT.LBR...
+
+

At this point, you will need to configure your ethernet adapter for your +local network using WIZCFG. The definitive guide to the use of +WIZCFG is on the cpnet-z80 +site in the document called “CPNET-WIZ850io.pdf”. Here is an example of +the commands needed to configure the WizNet:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
wizcfg w n F0set CP/NET node id
wizcfg w i 192.168.1.201set WizNet IP address
wizcfg w g 192.168.1.1set local network gateway IP address
wizcfg w s 255.255.255.0set WizNet subnet mask
wizcfg w 0 00 192.168.1.3 31100set server node ID, IP address, & port
+

You will need to use values appropriate for your local network. You can +use the command wiznet w to display the current values which is useful +to confirm they have been set as intended.

+
A>wizcfg w
+Node ID:  F0H
+IP Addr:  192.168.1.201
+Gateway:  192.168.1.1
+Subnet:   255.255.255.0
+MAC:      98:76:B6:11:00:C4
+Socket 0: 00H 192.168.1.3 31100 0
+
+

These values can be persisted across power-cycles if your system has +NVRAM storage. To program the values into your NVRAM, you would use the +same commands as above, but omit the w parameter. The +“CPNET-WIZ850io.pdf” document is highly recommended to understand the +operation of WIZCFG.

+

If you do not utilize NVRAM to persist your configuration, you will need +to reapply these commands every time you power cycle your RomWBW +computer, so I recommend putting them into a SUBMIT file.

+

After applying these commands, you should be able ping the WizNet from +another computer on the local network. If this works, then the +client-side is ready.

+

CP/NET Sever Setup

+

These instructions will assume you are using Douglas Miller’s +CpnetSocketServer to implement a CP/NOS server on your network. The +definitive guide to this software is also on the [cpnet-z80] +(https://github.com/durgadas311/cpnet-z80) site and is called +“CpnetSocketServer.pdf”.

+

The software is a Java application, so it can generally run anywhere +there is a Java runtime environment available. I have normally used it +on a Linux system and have had good results with that.

+

You will need to download the application called “CpnetSocketServer.jar” +from the cpnet-z80 site. The +application uses a configuration file. My configuration file is called +“cpnet00.rc” and has these contents:

+
cpnetserver_host = 192.168.1.3
+cpnetserver_port = 31100
+cpnetserver_temp = P
+cpnetserver_sid = 00
+cpnetserver_max = 16
+cpnetserver_root_dir = /home/wayne/cpnet/root
+
+

You will also need to setup a directory structure with the drive letters +per the documentation.

+

To start the server, you would use a command like this:

+

java -jar CpnetSocketServer.jar conf=cpnet00.rc

+

At this point, the server should start and you should see the following:

+
CpnetSocketServer v1.3
+Using config in cpnet00.rc
+Server 00 Listening on 192.168.1.3 port 31100 debug false
+
+

Your CP/NET server should now be ready to accept client connections.

+

CP/NET Usage

+

With both the client and server configured, you are ready to load and +use CP/NET on your RomWBW system. CP/NET documentation is available on +the cpnet-z80 site. The +document is called “dri-cpnet.pdf”.

+

Under CP/M 2.2, you will start the networking client using the command +CPNETLDR. Under CP/M 3, you use the command NDOS3. If that works, +you can map network drives as local drives using the NETWORK command. +The CPNETSTS command is useful for displaying the current status. Here +is a sample session from CP/M 2.2:

+
A>cpnetldr
+
+
+CP/NET 1.2 Loader
+=================
+
+BIOS         E600H  1A00H
+BDOS         D800H  0E00H
+SNIOS   SPR  D400H  0400H
+NDOS    SPR  C800H  0C00H
+TPA          0000H  C800H
+
+CP/NET 1.2 loading complete.
+
+A>network k:=c:[0]
+
+A>dir k:
+K: TELNET   COM : ZDENST   COM : CLRDIR   COM : RTC      COM
+K: DDTZ     COM : MBASIC   COM : XSUBNET  COM : NETWORK  COM
+K: WGET     COM : UNCR     COM : FLASH    COM : PIP      COM
+K: TIMEZONE COM : COMPARE  COM : ZAP      COM
+
+A>cpnetsts
+
+CP/NET 1.2 Status
+=================
+Requester ID = F0H
+Network Status Byte = 10H
+Disk device status:
+  Drive A: = LOCAL
+  Drive B: = LOCAL
+  Drive C: = LOCAL
+  Drive D: = LOCAL
+  Drive E: = LOCAL
+  Drive F: = LOCAL
+  Drive G: = LOCAL
+  Drive H: = LOCAL
+  Drive I: = LOCAL
+  Drive J: = LOCAL
+  Drive K: = Drive C: on Network Server ID = 00H
+  Drive L: = LOCAL
+  Drive M: = LOCAL
+  Drive N: = LOCAL
+  Drive O: = LOCAL
+  Drive P: = LOCAL
+Console Device = LOCAL
+List Device = LOCAL
+
+

If you are using CpSocketServer to provide the CP/NOS server, then you +will see some messages on your server console when clients connect. Here +are the messages issued by the server in the above example:

+
Connection from 192.168.1.201 (31100)
+Remote 192.168.1.201 is f0
+Creating HostFileBdos 00 device with root dir /home/wayne/cpnet/root
+
+

At this point CP/NET is ready for general use. You should be able to +access files on the network mapped drives just like files on your local +drives.

+

Network Boot

+

It is possible to boot your RomWBW system directly from a network server +if it has the required hardware. This means that the operating system +will be loaded directly from the network server and all of your drive +letters will be provided by the network server. The supported hardware +is:

+
    +
  • RCBus System w/ MT011 including:
  • +
  • Featherwing WizNet W5500
  • +
  • SPI FRAM on secondary SPI interface (CS2)
  • +
  • Doudyne Disk I/O Board including:
  • +
  • WIZ850io Module
  • +
  • 25LCxxx Serial SPI EEPROM
  • +
+

Unlike the CP/NET Client, the presence of dedicated non-volatile storage +is required to hold the network configuration. This will be FRAM (for +MT011) or Serial SPI EEPROM (Duodyne). The NVRAM is used to store your +WizNet configuration values so they do not need to be re-entered every +time you power-cycle your system.

+

It is important to understand that the operating system that is loaded +in this case is not a RomWBW enhanced operating system. Some +commands (such as the ASSIGN command) will not be possible. Also, you +will only have access to drives provided by the network server – no +local disk drives will be available.

+

Using the same values from the previous example, you would issue the +WIZCFG commands:

+
wizcfg n F0
+wizcfg i 192.168.1.201
+wizcfg g 192.168.1.1
+wizcfg s 255.255.255.0
+wizcfg 0 00 192.168.1.3 31100
+
+

Note that the ‘w’ parameter is now omitted which causes these values to +be written to NVRAM.

+

As before, your network server will need to be running +CpnetSocketServer. However, you will need to setup a directory that +contains some files that will be sent to your RomWBW system when the +Network boot is performed. By default the directory will be ~/NetBoot. +In this directory you need to place the following files:

+
    +
  • cpnos.sys
  • +
  • ndos.spr
  • +
  • snios.spr
  • +
+

You also need to make sure CpnetSocketServer is configured with an ‘A’ +drive and that drive must contain (at an absolute minimum) the following +file:

+
    +
  • ccp.spr
  • +
+

All of these files are found in the Binary/CPNET/NetBoot directory of +the RomWBW distribution. You will find 2 sub-directories named MT and +DUO. Get the files from the sub-directory corresponding to your specific +hardware.

+

Finally, you need to add the following line to your CpnetSocketServer +configuration file:

+

netboot_default = cpnos.sys

+

To perform the network boot, you start your RomWBW system normally which +should leave you at the Boot Loader prompt. The ‘N’ command will +initiate the network boot. Here is an example of what this looks like:

+
RCBus [RCZ180_nat_wbw] Boot Loader
+
+Boot [H=Help]: n
+
+Loading Network Boot...
+MT011 WizNET Network Boot
+
+WBWBIOS  SPR  FD00 0100
+COBDOS   SPR  FA00 0300
+SNIOS    SPR  F600 0400
+NDOS     SPR  EA00 0C00
+
+58K TPA
+
+A>
+
+

The CP/M operating system and the CP/NET components have been loaded +directly from the network server. All of your drive letters are +automatically mapped directly to the drive letters configured with +CpnetSocketServer.

+
A>cpnetsts
+
+CP/NET 1.2 Status
+=================
+Requester ID = F0H
+Network Status Byte = 10H
+Disk device status:
+  Drive A: = Drive A: on Network Server ID = 00H
+  Drive B: = Drive B: on Network Server ID = 00H
+  Drive C: = Drive C: on Network Server ID = 00H
+  Drive D: = Drive D: on Network Server ID = 00H
+  Drive E: = Drive E: on Network Server ID = 00H
+  Drive F: = Drive F: on Network Server ID = 00H
+  Drive G: = Drive G: on Network Server ID = 00H
+  Drive H: = Drive H: on Network Server ID = 00H
+  Drive I: = Drive I: on Network Server ID = 00H
+  Drive J: = Drive J: on Network Server ID = 00H
+  Drive K: = Drive K: on Network Server ID = 00H
+  Drive L: = Drive L: on Network Server ID = 00H
+  Drive M: = Drive M: on Network Server ID = 00H
+  Drive N: = Drive N: on Network Server ID = 00H
+  Drive O: = Drive O: on Network Server ID = 00H
+  Drive P: = Drive P: on Network Server ID = 00H
+Console Device = LOCAL
+List Device = LOCAL
+
+

At this point you can use CP/M and CP/NET normally, but all disk access +will be to/from the network drives. There is no access to your local +disk drives in this boot mode.

+

Transferring Files

+

Transferring files between your modern computer and your RomWBW system +can be achieved in a variety of ways. The most common of these are +described below. All of these have a certain degree of complexity and I +encourage new users to use the available community forums to seek +assistance as needed.

+

Serial Port Transfers

+

RomWBW provides an serial file transfer program called XModem that has +been adapted to run under RomWBW hardware. The program is called XM +and is on your ROM disk as well as all of the pre-built disk images.

+

You can type XM by itself to get usage information. In general, you +will run XM with parameters to indicate you want to send or receive a +file on your RomWBW system. Then, you will use your modern computers +terminal program to complete the process.

+

The XM application generally tries to detect the hardware you are +using and adapt to it. However, you must ensure that you have a reliable +serial connection. You must also ensure that the speed of the connection +is not too fast for XModem to service. If your file transfer attempts +are failing, try either of the following:

+
    +
  • Check that hardware flow control is enabled in your terminal emulation + software.
  • +
  • Reduce the speed of your serial port connection.
  • +
+

There is an odd interaction between XModem and partner terminal programs +that can occur. Essentially, after launching XM, you must start the +protocol on your modern computer fairly quickly (usually in about 20 +seconds or so). So, if you do not pick a file on your modern computer +quickly enough, you will find that the transfer completes about 16K, +then hangs. The interaction that causes this is beyond the scope of this +document.

+

Disk Image Transfers

+

It is possible to pass disk images between your RomWBW system and your +modern computer. This assumes you have an appropriate media slot on your +modern computer for the media you want to use (CF Card, SD Card, floppy +drive, etc.).

+

The general process to get files from your modern computer to a RomWBW +computer is:

+
    +
  1. +

    Use cpmtools on your modern computer to create a RomWBW CP/M + filesystem image.

    +
  2. +
  3. +

    Insert your RomWBW media (CF Card, SD Card, floppy disk, etc.) in + your modern computer.

    +
  4. +
  5. +

    Use a disk imaging tool to copy the RomWBW filesystem image onto the + media.

    +
  6. +
  7. +

    Move the media back to the RomWBW computer.

    +
  8. +
+

This process is a little complicated, but it has the benefit of allowing +you to get a lot of files over to your RomWBW system quickly and with +little chance of corruption.

+

The process can be run in reverse to get files from your RomWBW computer +to a modern computer.

+

The exact use of these tools is a bit too much for this document, but +the tools are all included in the RomWBW distribution along with usage +documents.

+

Note that the build scripts for RomWBW create the default disk images +supplied with RomWBW. It is relatively easy to customize the contents of +the disk images that are part of RomWBW. This is described in more +detail in the Source/Images directory of the distribution.

+

FAT Filesystem Transfers

+

The FAT filesystem format that originated with MS-DOS is almost +ubiquitous across modern computers. Virtually all operating systems now +support reading and writing files to a FAT filesystem. For this reason, +RomWBW now has the ability to read and write files on FAT filesystems.

+

This capability means that you can generally use your modern computer to +make an SD Card, CF Card, or USB Drive with a standard FAT filesystem on +it, then place that media in your RomWBW computer and access the files.

+
    +
  • +

    Files can be copied between a FAT filesystem and a CP/M filesystem, + but you cannot execute files directly from a FAT filesystem.

    +
  • +
  • +

    FAT12, FAT16, and FAT32 formats are supported.

    +
  • +
  • +

    Long filenames are not supported. Files with long filenames will show + up with their names truncated into the older 8.3 convention. If you + have files on your modern computer with long filenames, it is usually + easiest to rename them on the modern computer.

    +
  • +
  • +

    A FAT filesystem can be located on floppy or hard disk media. For hard + disk media, a valid FAT Filesystem partition must exist.

    +
  • +
+

Some additional Notes and WARNINGS Things to be careful about

+
    +
  • CP/M (and compatible) OSes do not support all of the filename + characters that a modern computer does. The following characters are + not permitted in a CP/M filename:
  • +
+

< > . , ; : = ? * [ ] _ % | ( ) / \

+

The FAT application does not auto-rename files when it encounters + invalid filenames. It will just issue an error and quit. Additionally, + the error message is not very clear about the problem.

+
    +
  • Microsoft Windows will sometimes suggest reformatting partitions + that it does not recognize (e.g. RomWBW). If you are using media that + contains both a FAT partition and a RomWBW partition you may prompted + to format a partition of your SD/CF/USB Media when inserting the card + into a Windows computer, you probably want to select Cancel.
  • +
+

FAT Filesystem Preparation

+

In general, you can create media formatted with a FAT filesystem on your +RomWBW computer or on your modern computer. We will only be discussing +the RomWBW-based approach here.

+

Floppy Disk

+

In the case of a floppy disk, you can use the FAT application to +format the floppy disk. The floppy disk must already be physically +formatted using RomWBW FDU or equivalent. If your floppy disk is on +RomWBW disk unit 2, you could use FAT FORMAT 2:. This will overwrite +the floppy with a FAT filesystem and all previous contents will be lost. +Once formatted this way, the floppy disk can be used in a floppy drive +attached to a modern computer or it can be used on RomWBW using the +other FAT tool commands.

+

Hard Disk

+

In the case of hard disk media, it is necessary to have a FAT partition. +If you prepared your RomWBW hard disk media using the disk image +process, then this partition will already be defined and you do not need +to recreate it. This default FAT partition is located at approximately +512MB from the start of your disk and it is 384MB in size. So, your hard +disk media must be 1GB or greater to use this default FAT partition.

+

You can confirm the existence of the FAT partition with FDISK80 by +using the ‘P’ command to show the current partition table. Here is an +example of a partition table listing from FDISK80 that includes the +FAT partition (labelled “FAT16”):

+
Capacity of disk 4:  (  4G)  7813120      Geom 77381010
+Nr  ---Type- A --      Start         End   LBA start  LBA count  Size
+ 1    RomWBW   2e      8:0:1  1023:15:16        2048    1048576  512M
+ 2     FAT16   06   1023:0:1  1023:15:16     1050624     786432  384M
+ 3             00       *** empty ***
+ 4             00       *** empty ***
+
+

If your hard disk media does not have a FAT partition already defined, +you will need to define one using FDISK80 by using the ‘N’ command. +Ensure that the location and size of the FAT partition does not overlap +any of the CP/M slice area and that it fits within the size of your +media.

+

Once the partition is defined, you will still need to format it. Just as +with a floppy disk, you use the FAT tool to do this. If your hard disk +media is on RomWBW disk unit 4, you would use FAT FORMAT 4:. This will +look something like this:

+
E>fat format 4:
+
+About to format FAT Filesystem on Disk Unit #4.
+All existing FAT partition data will be destroyed!!!
+
+Continue (y/n)?
+
+Formatting... Done
+
+

Your FAT filesystem is now ready to use.

+

If your RomWBW system has multiple disk drives/slots, you can also just +create a disk with your modern computer that is a dedicated FAT +filesystem disk. You can use your modern computer to format the disk +(floppy, CF Card, SD Card, etc.), then insert the disk in your RomWBW +computer and access it using FAT based on its RomWBW unit number.

+

FAT Application Usage

+

Transferring files is accomplished by running a RomWBW custom +application called FAT. This application understands both FAT +filesystems as well as CP/M filesystems.

+

To copy files from your modern computer to your RomWBW computer, start +by putting the disk media with the FAT filesystem in your modern +computer. The modern computer should recognize it. Then copy the files +you want to get to your RomWBW computer onto this media. Once done, +remove the media from your modern computer and insert it in the RomWBW +computer.

+

Finally, use the FAT tool to copy the files onto a CP/M drive. This +process works just fine in reverse if you want to copy files from a CP/M +filesystem to your modern computer.

+

Complete instructions for the FAT application are found in RomWBW +Applications. +Here, we will just provide a couple of simple examples. Note that the +FAT application is not on the ROM disk because it is too large to +include there.

+

The most important thing to understand about the FAT application is +how it refers to FAT filesystems vs. CP/M filesystems. It infers this +based on the file specification provided. If you use a specification +like C:SAMPLE.TXT, it will use the C: drive of your CP/M operating +system. If you use a specification like 4:SAMPLE.TXT, it will use the +FAT filesystem on the disk in RomWBW disk unit 4. Basically, if you +start your file or directory specification with a number followed by a +colon, it means FAT filesystem. Anything else will mean CP/M filesystem.

+

Here are a few examples. This first example shows how to get a FAT +directory listing from RomWBW disk unit 4:

+
E>fat dir 4:
+
+Directory of 4:
+
+
+E>
+
+

As you can see, there are currently no files there. Now let’s copy a +file from CP/M to the FAT directory:

+
E>fat copy sample.txt 4:
+
+Copying...
+
+SAMPLE.TXT ==> 4:/SAMPLE.TXT ... [OK]
+
+    1 File(s) Copied
+
+

If we list the FAT directory again, you will see the file:

+
E>fat dir 4:
+
+Directory of 4:
+
+01/30/2023  17:50:14         29952  ---A  SAMPLE.TXT
+
+

Now let’s copy the file from the FAT filesystem back to CP/M. This time +we will get a warning about overwriting the file. For this example, we +don’t want to do that, so we abort and reissue the command specifying a +new filename to use:

+
E>fat copy 4:sample.txt e:
+
+Copying...
+
+4:/SAMPLE.TXT ==> E:SAMPLE.TXT Overwrite? (Y/N) [Skipped]
+
+    0 File(s) Copied
+
+E>fat copy 4:sample.txt e:sample2.txt
+
+Copying...
+
+4:/SAMPLE.TXT ==> E:SAMPLE2.TXT ... [OK]
+
+    1 File(s) Copied
+
+

Finally, let’s try using wildcards:

+
E>fat copy sample*.* 4:
+
+Copying...
+
+SAMPLE.TXT ==> 4:/SAMPLE.TXT Overwrite? (Y/N) ... [OK]
+SAMPLE2.TXT ==> 4:/SAMPLE2.TXT ... [OK]
+
+    2 File(s) Copied
+
+

Customizing RomWBW

+

Startup Command Processing

+

Most of the operating systems supported by RomWBW provide a mechanism to +run commands at boot. This is similar to the AUTOEXEC.BAT files from +MS-DOS.

+

With the exception of ZPM3 and p-System, all operating systems will look +for a file called PROFILE.SUB on the system drive at boot. If it is +found, it will be processed as a standard CP/M submit file. You can read +about the use of the SUBMIT facility in the CP/M manuals included in the +RomWBW distribution. Note that the boot disk must also have a copy of +SUBMIT.EXE.

+

Note that the automatic startup processing generally requires booting to +a disk drive. Since the ROM disk is not writable, there is no simple way +to add/edit a PROFILE.SUB file there. If you want to customize your +ROM and add a PROFILE.SUB file to the ROM Disk, it will work, but is a +lot harder than using a boot disk.

+

In the case of ZPM3, the file called STARTZPM.COM will be run at boot. +To customize this file, you use the ZCPR ALIAS facility. You will need +to refer to ZCPR documentation for more information on the ALIAS +facility.

+

p-System has its own startup command processing mechanism that is +covered in the p-System documentation.

+

NVRAM Configuration

+

See section Setting NVRAM Options for +information about how to apply NVRAM configuration.

+

ROM Customization

+

The pre-built ROM images are configured for the basic capabilities of +each platform. Additionally, some of the typical add-on hardware for +each platform will be automatically detected and used. If you want to go +beyond this, RomWBW provides a very flexible configuration mechanism +based on configuration files. Creating a customized ROM requires running +a build script, but it is quite easy to do.

+

Essentially, the creation of a custom ROM is accomplished by updating a +small configuration file, then running a script to compile the software +and generate the custom ROM and disk images. There are build scripts for +Windows, Linux, and MacOS to accommodate virtually all users. All +required build tools (compilers, assemblers, etc.) are included in the +distribution, so it is not necessary to setup a build environment on +your computer.

+

RomWBW can be built on modern Windows, Linux, or MacOS computers. The +process for building a custom ROM is documented in the ReadMe.txt file +in the Source directory of the distribution. Any modern version of +Windows (32-bit or 64-bit), MacOS, or Linux released in the last 10 +years should be able to run the build process.

+

For those who are interested in more than basic system customization, +note that all source code is provided (including the operating systems). +Modification of the source code is considered an expert level task and +is left to the reader to pursue.

+

Note that the ROM customization process does not apply to UNA. All UNA +customization is performed within the ROM setup script that is built +into the ROM.

+

ROM User Application

+

The User App is provided as a way to access a custom written ROM +application. In the pre-built ROMs, selecting User App will just return +to the Boot Loader menu. If you are interested in creating a custom +application to run instead, review the “usrrom.asm” file in the +Source/HBIOS folder of the distribution.

+

Upgrading

+

Upgrading to a newer release of RomWBW is essentially just a matter of +updating the ROM chip in your system. If you have spare ROM chips for +your system and a ROM programmer, it is always safest to retain your +existing, working ROM chip and program a new one with the new firmware. +If the new one fails to boot, you can easily return to the known working +ROM.

+

For each ROM that comes with the RomWBW distribution, you will find that +there are actually 3 different variants:

+
    +
  • .rom contains the complete ROM chip image
  • +
  • .upd contains the system code, but omits the ROM Disk contents
  • +
  • .com contains a CP/M executable version of the ROM code
  • +
+

So, for example, RCZ80_std contains the following files:

+
    +
  • SBC_std.rom
  • +
  • SBC_std.upd
  • +
  • SBC_std.com
  • +
+

The use of the .com variant is described below in Application +Boot.

+

As previously discussed, the ROM in most RomWBW systems contains both +the system code as well as a ROM Disk with files on it. The .rom +variant of the ROM contains a full ROM chip image including both the +system code and the Rom Disk contents. The .upd variant of the ROM +contains only the system code portion of the ROM. If you apply the +.upd variant to your system, it will overlay the system code, but will +not overlay the ROM Disk contents (they remain intact). You may use +either the .rom or the .upd file when updating your ROM chip (this +does not apply to Application Boot). It is best to use the .rom file +for your upgrade because the files on your ROM Disk should be updated +whenever you update your system code. The advantage of the .upd +variant is that is much smaller, so you can upload and apply it faster. +The ROM update instructions below generally refer to using the .rom +variant. However, you may substitute the .upd variant if desired.

+

Application Boot

+

Prior to attempting to reprogram your actual ROM chip, you may wish to +“try” the update to ensure it will work on your system. With RomWBW, you +can upload a new ROM image executable and load it from the command line. +For each ROM image file (.rom) in the Binary directory, you will find a +corresponding application file (.com). For example, for SBC_std.rom, +there is also an SBC_std.com file.

+

You can upload the .com file to your system using XModem, then simply +run the .com file. You will see your system go through the normal +startup process just like it was started from ROM. However, your +physical ROM has not been updated and the next time you boot your +system, it will revert to the system image contained in ROM.

+

Using this .com version of a ROM is an excellent way to confirm that +the new ROM code you intend to program will work correctly. If it does +not, then you can just reboot and your old ROM will be loaded.

+

When the .com file is loaded, you will be taken to the normal Boot +Loader menu. However, you will find that the only OS that is available +to boot from ROM is ZSDOS. There is only room for a single OS in the +.com file. Even if you don’t normally use ZSDOS, this will still confirm +that your system operates well under the new ROM code.

+

Upgrading via Flash Utility

+

If you do not have easy access to a ROM programmer, it is usually +possible to reprogram your system ROM using the FLASH utility from Will +Sowerbutts. This application, called FLASH.COM, can be found on the ROM +drive of any running system. In this case, you would need to transfer +the new ROM image (.rom) over to your system using XModem (or one of the +other mechanisms described in the Transferring +Files section). The ROM image is too large to fit +on your RAM drive, so you will need to transfer it to a larger storage +drive. Once the ROM image is on your system, you can use the FLASH +application to update your ROM. The following is a typical example of +transferring ROM image using XModem and flashing the chip in-situ.

+

NOTE: The FLASH utility can not determine the type of your ROM +chip if it is write protected. Additionally, it has no way to determine +if it is write protected. If the FLASH utility indicates it does not +recognize your ROM chip, check to ensure the chip is not write +protected.

+
E>xm r rom.rom
+
+XMODEM v12.5 - 07/13/86
+RBC, 28-Aug-2019 [WBW], ASCI
+
+Receiving: E0:ROM.IMG
+7312k available for uploads
+File open - ready to receive
+To cancel: Ctrl-X, pause, Ctrl-X
+
+Thanks for the upload
+
+E>flash write rom.rom
+FLASH4 by Will Sowerbutts <will@sowerbutts.com> version 1.2.3
+
+Using RomWBW (v2.6+) bank switching.
+Flash memory chip ID is 0xBFB7: 39F040
+Flash memory has 128 sectors of 4096 bytes, total 512KB
+Write complete: Reprogrammed 2/128 sectors.
+Verify (128 sectors) complete: OK!
+
+

Obviously, there is some risk to this approach since any issues with the +programming or ROM image could result in a non-functional system.

+

To confirm your ROM chip has been successfully updated, restart your +system and boot an operating system from ROM. Do not boot from a disk +device yet. Review the boot messages to see if any issues have occurred.

+

Upgrading via XModem Flash Updater

+

Similar to using the Flash utility, the system ROM can be updated or +upgraded through the ROM-based updater utility. This works by +reprogramming the flash ROM as the file is being transferred.

+

Using the ROM-based updater has the advantage that secondary storage is +not required to hold the new image. In other words, it is not necessary +to have a mass storage device available to store the ROM image.

+

From the Boot Loader menu select X (Xmodem Flash Updater) and then U +(Begin Update). Then initiate the Xmodem transfer of the .rom file. +Since the XModem Flash Updater will be relatively slow, you may wish to +use the .upd varient of the ROM.

+

More information can be found in the ROM Applications document.

+

Post Upgrade Update

+

Once you are satisfied that the ROM is working well, you will need to +update the system images and RomWBW custom applications on your disk +drives. The system images and custom applications are matched to the +RomWBW ROM firmware in use. If you attempt to boot a disk or run +applications that have not been updated to match the current ROM +firmware, you are likely to have odd problems.

+

The simplest way to update your disk media is to just use your modern +computer to overwrite the entire media with the latest disk image of +your choice. This process is described below in the Disk +Images section. If you wish to update existing disk media +in your system, you need to perform the following steps.

+

If the disk is bootable, you need to update the system image on the disk +using the procedure described in the Operating +Systems section of this document.

+

Finally, if you have copies of any of the RomWBW custom applications on +your hard disk, you need to update them with the latest copies. The +following applications are found on your ROM disk. Use COPY to copy them +over any older versions of the app on your disk:

+
    +
  • ASSIGN.COM
  • +
  • SYSCOPY.COM
  • +
  • MODE.COM
  • +
  • FDU.COM
  • +
  • FORMAT.COM
  • +
  • XM.COM
  • +
  • FLASH.COM
  • +
  • FDISK80.COM
  • +
  • TALK.COM
  • +
  • RTC.COM
  • +
  • TIMER.COM
  • +
  • FAT.COM
  • +
+

For example: B>COPY ASSIGN.COM C:

+

Some RomWBW custom applications are too large to fit on the ROM disk. If +you are using any of these you will need to transfer them to your system +and then update all copies. These applications are found in the +Binary/Apps directory of the distribution and in all of the disk images.

+
    +
  • TUNE.COM
  • +
+

The files normally contained on the standard ROM Disk is based on a 512K +ROM. If your system has a smaller size ROM, then not all of these files +will be included on your ROM Disk. You will need to copy them to your +system from the /Binary/Apps folder of the RomWBW distribution.

+

WARNING: If you run a RomWBW-specific application that is not the +appropriate for the version of RomWBW you are running, the application +will generate an error message and abort.

+

System Update

+

As previously described, a RomWBW ROM contains ROM applications as well +as a ROM disk image. If you are upgrading your ROM with a new patch +level release, you may wish to upgrade just the application portion of +the ROM. This is referred to as a System Update.

+

If the system running ROMWBW utilizes the SST39SF040 Flash chip then it +is possible to do a System Update in place of a System Upgrade in some +cases. A System Update would involve only updating the BIOS, ROM +applications and ROM-hosted operating systems.

+

A System Update may be more favorable than a System Upgrade in cases +such as:

+
    +
  • Overwriting of the ROM drive contents is not desired.
  • +
  • Temporary disk space is unavailable to hold a full ROM image.
  • +
  • To reduce the time taken to transfer and flash a full ROM.
  • +
  • Configuration changes are only minor and do not impact disk + applications.
  • +
+

The RomWBW build process generates a system update file along with the +normal ROM image and can be identified by the extension “.upd”. It will +be 128Kb in size. In comparison the normal ROM image will have the +extension “.rom” and be 512Kb or 1024Kb in size.

+

Transferring and flashing the System Update is accomplished in the same +manner as described above in Upgrading via Flash +Utility with the required difference +being that the flash application needs to be directed to complete a +partial flash using the /P command line switch.

+

E>FLASH WRITE ROM.UPD /P

+
+
+ + + + + + + + + + + diff --git a/css/base.css b/css/base.css new file mode 100644 index 00000000..f5f27ba7 --- /dev/null +++ b/css/base.css @@ -0,0 +1,366 @@ +html { + /* The nav header is 3.5rem high, plus 20px for the margin-top of the + main container. */ + scroll-padding-top: calc(3.5rem + 20px); +} + +/* Replacement for `body { background-attachment: fixed; }`, which has + performance issues when scrolling on large displays. See #1394. */ +body::before { + content: ' '; + position: fixed; + width: 100%; + height: 100%; + top: 0; + left: 0; + background-color: var(--bs-body-bg); + background: url(../img/grid.png) repeat-x; + will-change: transform; + z-index: -1; +} + +body > .container { + margin-top: 20px; + min-height: 400px; +} + +.navbar.fixed-top { + position: -webkit-sticky; + position: sticky; +} + +.source-links { + float: right; +} + +.col-md-9 img { + max-width: 100%; + display: inline-block; + padding: 4px; + line-height: 1.428571429; + background-color: var(--bs-secondary-bg-subtle); + border: 1px solid var(--bs-secondary-border-subtle); + border-radius: 4px; + margin: 20px auto 30px auto; +} + +h1 { + color: inherit; + font-weight: 400; + font-size: 42px; +} + +h2, h3, h4, h5, h6 { + color: inherit; + font-weight: 300; +} + +hr { + border-top: 1px solid #aaa; + opacity: 1; +} + +pre, .rst-content tt { + max-width: 100%; + background-color: var(--bs-body-bg); + border: solid 1px var(--bs-border-color); + color: var(--bs-body-color); + overflow-x: auto; +} + +code.code-large, .rst-content tt.code-large { + font-size: 90%; +} + +code { + padding: 2px 5px; + background-color: rgba(var(--bs-body-bg-rgb), 0.75); + border: solid 1px var(--bs-border-color); + color: var(--bs-body-color); + white-space: pre-wrap; + word-wrap: break-word; +} + +pre code { + display: block; + border: none; + white-space: pre; + word-wrap: normal; + font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; + font-size: 12px; +} + +kbd { + padding: 2px 4px; + font-size: 90%; + color: var(--bs-secondary-text-emphasis); + background-color: var(--bs-secondary-bg-subtle); + border-radius: 3px; + -webkit-box-shadow: inset 0 -1px 0 rgba(0,0,0,.25); + box-shadow: inset 0 -1px 0 rgba(0,0,0,.25); +} + +a code { + color: inherit; +} + +a:hover code, a:focus code { + color: inherit; +} + +footer { + margin-top: 30px; + margin-bottom: 10px; + text-align: center; + font-weight: 200; +} + +.modal-dialog { + margin-top: 60px; +} + +/* + * Side navigation + * + * Scrollspy and affixed enhanced navigation to highlight sections and secondary + * sections of docs content. + */ + +.bs-sidebar.affix { + position: -webkit-sticky; + position: sticky; + /* The nav header is 3.5rem high, plus 20px for the margin-top of the + main container. */ + top: calc(3.5rem + 20px); +} + +.bs-sidebar.card { + padding: 0; + max-height: 90%; + overflow-y: auto; +} + +/* Toggle (vertically flip) sidebar collapse icon */ +.bs-sidebar .navbar-toggler span { + -moz-transform: scale(1, -1); + -webkit-transform: scale(1, -1); + -o-transform: scale(1, -1); + -ms-transform: scale(1, -1); + transform: scale(1, -1); +} + +.bs-sidebar .navbar-toggler.collapsed span { + -moz-transform: scale(1, 1); + -webkit-transform: scale(1, 1); + -o-transform: scale(1, 1); + -ms-transform: scale(1, 1); + transform: scale(1, 1); +} + +/* First level of nav */ +.bs-sidebar > .navbar-collapse > .nav { + padding-top: 10px; + padding-bottom: 10px; + border-radius: 5px; + width: 100%; +} + +/* All levels of nav */ +.bs-sidebar .nav > li > a { + display: block; + padding: 5px 20px; + z-index: 1; +} +.bs-sidebar .nav > li > a:hover, +.bs-sidebar .nav > li > a:focus { + text-decoration: none; + border-right: 1px solid; +} +.bs-sidebar .nav > li > a.active, +.bs-sidebar .nav > li > a.active:hover, +.bs-sidebar .nav > li > a.active:focus { + font-weight: bold; + background-color: transparent; + border-right: 1px solid; +} + +.bs-sidebar .nav .nav .nav { + margin-left: 1em; +} + +.bs-sidebar .nav > li > a { + font-weight: bold; +} + +.bs-sidebar .nav .nav > li > a { + font-weight: normal; +} + +.headerlink { + font-family: FontAwesome; + font-size: 14px; + display: none; + padding-left: .5em; + text-decoration: none; + vertical-align: middle; +} + +h1:hover .headerlink, h2:hover .headerlink, h3:hover .headerlink, h4:hover .headerlink, h5:hover .headerlink, h6:hover .headerlink { + display:inline-block; +} + +blockquote { + padding-left: 10px; + border-left: 4px solid #e6e6e6; +} + +.admonition, details { + padding: 15px; + margin-bottom: 20px; + border: 1px solid transparent; + border-radius: 4px; + text-align: left; +} + +.admonition.note, details.note { + color: var(--bs-primary-text-emphasis); + background-color: var(--bs-primary-bg-subtle); + border-color: var(--bs-primary-border-subtle); +} + +.admonition.note h1, .admonition.note h2, .admonition.note h3, +.admonition.note h4, .admonition.note h5, .admonition.note h6, +details.note h1, details.note h2, details.note h3, +details.note h4, details.note h5, details.note h6 { + color: var(--bs-primary-text-emphasis); +} + +.admonition.info, details.info { + color: var(--bs-info-text-emphasis); + background-color: var(--bs-info-bg-subtle); + border-color: var(--bs-info-border-subtle); +} + +.admonition.info h1, .admonition.info h2, .admonition.info h3, +.admonition.info h4, .admonition.info h5, .admonition.info h6, +details.info h1, details.info h2, details.info h3, +details.info h4, details.info h5, details.info h6 { + color: var(--bs-info-text-emphasis); +} + +.admonition.warning, details.warning { + color: var(--bs-warning-text-emphasis); + background-color: var(--bs-warning-bg-subtle); + border-color: var(--bs-warning-border-subtle); +} + +.admonition.warning h1, .admonition.warning h2, .admonition.warning h3, +.admonition.warning h4, .admonition.warning h5, .admonition.warning h6, +details.warning h1, details.warning h2, details.warning h3, +details.warning h4, details.warning h5, details.warning h6 { + color: var(--bs-warning-text-emphasis); +} + +.admonition.danger, details.danger { + color: var(--bs-danger-text-emphasis); + background-color: var(--bs-danger-bg-subtle); + border-color: var(--bs-danger-border-subtle); +} + +.admonition.danger h1, .admonition.danger h2, .admonition.danger h3, +.admonition.danger h4, .admonition.danger h5, .admonition.danger h6, +details.danger h1, details.danger h2, details.danger h3, +details.danger h4, details.danger h5, details.danger h6 { + color: var(--bs-danger-text-emphasis); +} + +.admonition, details { + color: var(--bs-light-text-emphasis); + background-color: var(--bs-light-bg-subtle); + border-color: var(--bs-light-border-subtle); +} + +.admonition h1, .admonition h2, .admonition h3, +.admonition h4, .admonition h5, .admonition h6, +details h1, details h2, details h3, +details h4, details h5, details h6 { + color: var(--bs-light-text-emphasis); +} + +.admonition-title, summary { + font-weight: bold; + text-align: left; +} + +.admonition>p:last-child, details>p:last-child { + margin-bottom: 0; +} + +@media (max-width: 991.98px) { + .navbar-collapse.show { + overflow-y: auto; + max-height: calc(100vh - 3.5rem); + } +} + +.dropdown-item.open { + color: var(--bs-dropdown-link-active-color); + background-color: var(--bs-dropdown-link-active-bg); +} + +.dropdown-submenu > .dropdown-menu { + margin: 0 0 0 1.5rem; + padding: 0; + border-width: 0; +} + +.dropdown-submenu > a::after { + display: block; + content: " "; + float: right; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; + border-width: 5px 0 5px 5px; + border-left-color: var(--bs-dropdown-link-active-color); + margin-top: 5px; + margin-right: -10px; +} + +.dropdown-submenu:hover > a::after { + border-left-color: var(--bs-dropdown-link-active-color); +} + +@media (min-width: 992px) { + .dropdown-menu { + overflow-y: auto; + max-height: calc(100vh - 3.5rem); + } + + .dropdown-submenu { + position: relative; + } + + .dropdown-submenu > .dropdown-menu { + position: fixed !important; + margin-top: -9px; + margin-left: -2px; + border-width: 1px; + padding: 0.5rem 0; + } + + .dropdown-submenu.pull-left { + float: none; + } + + .dropdown-submenu.pull-left > .dropdown-menu { + left: -100%; + margin-left: 10px; + } +} + +@media print { + /* Remove sidebar when print */ + .col-md-3 { display: none; } +} diff --git a/css/bootstrap.min.css b/css/bootstrap.min.css new file mode 100644 index 00000000..0eed851a --- /dev/null +++ b/css/bootstrap.min.css @@ -0,0 +1,12 @@ +@charset "UTF-8";/*! + * Bootswatch v5.3.2 (https://bootswatch.com) + * Theme: cerulean + * Copyright 2012-2023 Thomas Park + * Licensed under MIT + * Based on Bootstrap +*//*! + * Bootstrap v5.3.2 (https://getbootstrap.com/) + * Copyright 2011-2023 The Bootstrap Authors + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + */:root,[data-bs-theme=light]{--bs-blue:#033c73;--bs-indigo:#6610f2;--bs-purple:#6f42c1;--bs-pink:#e83e8c;--bs-red:#c71c22;--bs-orange:#fd7e14;--bs-yellow:#dd5600;--bs-green:#73a839;--bs-teal:#20c997;--bs-cyan:#2fa4e7;--bs-black:#000;--bs-white:#fff;--bs-gray:#868e96;--bs-gray-dark:#343a40;--bs-gray-100:#f8f9fa;--bs-gray-200:#e9ecef;--bs-gray-300:#dee2e6;--bs-gray-400:#ced4da;--bs-gray-500:#adb5bd;--bs-gray-600:#868e96;--bs-gray-700:#495057;--bs-gray-800:#343a40;--bs-gray-900:#212529;--bs-primary:#2fa4e7;--bs-secondary:#e9ecef;--bs-success:#73a839;--bs-info:#033c73;--bs-warning:#dd5600;--bs-danger:#c71c22;--bs-light:#f8f9fa;--bs-dark:#343a40;--bs-primary-rgb:47,164,231;--bs-secondary-rgb:233,236,239;--bs-success-rgb:115,168,57;--bs-info-rgb:3,60,115;--bs-warning-rgb:221,86,0;--bs-danger-rgb:199,28,34;--bs-light-rgb:248,249,250;--bs-dark-rgb:52,58,64;--bs-primary-text-emphasis:#13425c;--bs-secondary-text-emphasis:#5d5e60;--bs-success-text-emphasis:#2e4317;--bs-info-text-emphasis:#01182e;--bs-warning-text-emphasis:#582200;--bs-danger-text-emphasis:#500b0e;--bs-light-text-emphasis:#495057;--bs-dark-text-emphasis:#495057;--bs-primary-bg-subtle:#d5edfa;--bs-secondary-bg-subtle:#fbfbfc;--bs-success-bg-subtle:#e3eed7;--bs-info-bg-subtle:#cdd8e3;--bs-warning-bg-subtle:#f8ddcc;--bs-danger-bg-subtle:#f4d2d3;--bs-light-bg-subtle:#fcfcfd;--bs-dark-bg-subtle:#ced4da;--bs-primary-border-subtle:#acdbf5;--bs-secondary-border-subtle:#f6f7f9;--bs-success-border-subtle:#c7dcb0;--bs-info-border-subtle:#9ab1c7;--bs-warning-border-subtle:#f1bb99;--bs-danger-border-subtle:#e9a4a7;--bs-light-border-subtle:#e9ecef;--bs-dark-border-subtle:#adb5bd;--bs-white-rgb:255,255,255;--bs-black-rgb:0,0,0;--bs-font-sans-serif:system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue","Noto Sans","Liberation Sans",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--bs-font-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--bs-gradient:linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));--bs-body-font-family:var(--bs-font-sans-serif);--bs-body-font-size:1rem;--bs-body-font-weight:400;--bs-body-line-height:1.5;--bs-body-color:#495057;--bs-body-color-rgb:73,80,87;--bs-body-bg:#fff;--bs-body-bg-rgb:255,255,255;--bs-emphasis-color:#000;--bs-emphasis-color-rgb:0,0,0;--bs-secondary-color:rgba(73, 80, 87, 0.75);--bs-secondary-color-rgb:73,80,87;--bs-secondary-bg:#e9ecef;--bs-secondary-bg-rgb:233,236,239;--bs-tertiary-color:rgba(73, 80, 87, 0.5);--bs-tertiary-color-rgb:73,80,87;--bs-tertiary-bg:#f8f9fa;--bs-tertiary-bg-rgb:248,249,250;--bs-heading-color:#2fa4e7;--bs-link-color:#2fa4e7;--bs-link-color-rgb:47,164,231;--bs-link-decoration:underline;--bs-link-hover-color:#2683b9;--bs-link-hover-color-rgb:38,131,185;--bs-code-color:#e83e8c;--bs-highlight-color:#495057;--bs-highlight-bg:#f8ddcc;--bs-border-width:1px;--bs-border-style:solid;--bs-border-color:#dee2e6;--bs-border-color-translucent:rgba(0, 0, 0, 0.175);--bs-border-radius:0.375rem;--bs-border-radius-sm:0.25rem;--bs-border-radius-lg:0.5rem;--bs-border-radius-xl:1rem;--bs-border-radius-xxl:2rem;--bs-border-radius-2xl:var(--bs-border-radius-xxl);--bs-border-radius-pill:50rem;--bs-box-shadow:0 0.5rem 1rem rgba(0, 0, 0, 0.15);--bs-box-shadow-sm:0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);--bs-box-shadow-lg:0 1rem 3rem rgba(0, 0, 0, 0.175);--bs-box-shadow-inset:inset 0 1px 2px rgba(0, 0, 0, 0.075);--bs-focus-ring-width:0.25rem;--bs-focus-ring-opacity:0.25;--bs-focus-ring-color:rgba(47, 164, 231, 0.25);--bs-form-valid-color:#73a839;--bs-form-valid-border-color:#73a839;--bs-form-invalid-color:#c71c22;--bs-form-invalid-border-color:#c71c22}[data-bs-theme=dark]{color-scheme:dark;--bs-body-color:#dee2e6;--bs-body-color-rgb:222,226,230;--bs-body-bg:#212529;--bs-body-bg-rgb:33,37,41;--bs-emphasis-color:#fff;--bs-emphasis-color-rgb:255,255,255;--bs-secondary-color:rgba(222, 226, 230, 0.75);--bs-secondary-color-rgb:222,226,230;--bs-secondary-bg:#343a40;--bs-secondary-bg-rgb:52,58,64;--bs-tertiary-color:rgba(222, 226, 230, 0.5);--bs-tertiary-color-rgb:222,226,230;--bs-tertiary-bg:#2b3035;--bs-tertiary-bg-rgb:43,48,53;--bs-primary-text-emphasis:#82c8f1;--bs-secondary-text-emphasis:#f2f4f5;--bs-success-text-emphasis:#abcb88;--bs-info-text-emphasis:#688aab;--bs-warning-text-emphasis:#eb9a66;--bs-danger-text-emphasis:#dd777a;--bs-light-text-emphasis:#f8f9fa;--bs-dark-text-emphasis:#dee2e6;--bs-primary-bg-subtle:#09212e;--bs-secondary-bg-subtle:#2f2f30;--bs-success-bg-subtle:#17220b;--bs-info-bg-subtle:#010c17;--bs-warning-bg-subtle:#2c1100;--bs-danger-bg-subtle:#280607;--bs-light-bg-subtle:#343a40;--bs-dark-bg-subtle:#1a1d20;--bs-primary-border-subtle:#1c628b;--bs-secondary-border-subtle:#8c8e8f;--bs-success-border-subtle:#456522;--bs-info-border-subtle:#022445;--bs-warning-border-subtle:#853400;--bs-danger-border-subtle:#771114;--bs-light-border-subtle:#495057;--bs-dark-border-subtle:#343a40;--bs-heading-color:inherit;--bs-link-color:#82c8f1;--bs-link-hover-color:#9bd3f4;--bs-link-color-rgb:130,200,241;--bs-link-hover-color-rgb:155,211,244;--bs-code-color:#f18bba;--bs-highlight-color:#dee2e6;--bs-highlight-bg:#582200;--bs-border-color:#495057;--bs-border-color-translucent:rgba(255, 255, 255, 0.15);--bs-form-valid-color:#abcb88;--bs-form-valid-border-color:#abcb88;--bs-form-invalid-color:#dd777a;--bs-form-invalid-border-color:#dd777a}*,::after,::before{box-sizing:border-box}@media (prefers-reduced-motion:no-preference){:root{scroll-behavior:smooth}}body{margin:0;font-family:var(--bs-body-font-family);font-size:var(--bs-body-font-size);font-weight:var(--bs-body-font-weight);line-height:var(--bs-body-line-height);color:var(--bs-body-color);text-align:var(--bs-body-text-align);background-color:var(--bs-body-bg);-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}hr{margin:1rem 0;color:inherit;border:0;border-top:var(--bs-border-width) solid;opacity:.25}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2;color:var(--bs-heading-color)}.h1,h1{font-size:calc(1.375rem + 1.5vw)}@media (min-width:1200px){.h1,h1{font-size:2.5rem}}.h2,h2{font-size:calc(1.325rem + .9vw)}@media (min-width:1200px){.h2,h2{font-size:2rem}}.h3,h3{font-size:calc(1.3rem + .6vw)}@media (min-width:1200px){.h3,h3{font-size:1.75rem}}.h4,h4{font-size:calc(1.275rem + .3vw)}@media (min-width:1200px){.h4,h4{font-size:1.5rem}}.h5,h5{font-size:1.25rem}.h6,h6{font-size:1rem}p{margin-top:0;margin-bottom:1rem}abbr[title]{-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}ol,ul{padding-left:2rem}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}.small,small{font-size:.875em}.mark,mark{padding:.1875em;color:var(--bs-highlight-color);background-color:var(--bs-highlight-bg)}sub,sup{position:relative;font-size:.75em;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:rgba(var(--bs-link-color-rgb),var(--bs-link-opacity,1));text-decoration:underline}a:hover{--bs-link-color-rgb:var(--bs-link-hover-color-rgb)}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:var(--bs-font-monospace);font-size:1em}pre{display:block;margin-top:0;margin-bottom:1rem;overflow:auto;font-size:.875em}pre code{font-size:inherit;color:inherit;word-break:normal}code{font-size:.875em;color:var(--bs-code-color);word-wrap:break-word}a>code{color:inherit}kbd{padding:.1875rem .375rem;font-size:.875em;color:var(--bs-body-bg);background-color:var(--bs-body-color);border-radius:.25rem}kbd kbd{padding:0;font-size:1em}figure{margin:0 0 1rem}img,svg{vertical-align:middle}table{caption-side:bottom;border-collapse:collapse}caption{padding-top:.5rem;padding-bottom:.5rem;color:var(--bs-secondary-color);text-align:left}th{text-align:inherit;text-align:-webkit-match-parent}tbody,td,tfoot,th,thead,tr{border-color:inherit;border-style:solid;border-width:0}label{display:inline-block}button{border-radius:0}button:focus:not(:focus-visible){outline:0}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}select:disabled{opacity:1}[list]:not([type=date]):not([type=datetime-local]):not([type=month]):not([type=week]):not([type=time])::-webkit-calendar-picker-indicator{display:none!important}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}::-moz-focus-inner{padding:0;border-style:none}textarea{resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{float:left;width:100%;padding:0;margin-bottom:.5rem;font-size:calc(1.275rem + .3vw);line-height:inherit}@media (min-width:1200px){legend{font-size:1.5rem}}legend+*{clear:left}::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-fields-wrapper,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-text,::-webkit-datetime-edit-year-field{padding:0}::-webkit-inner-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-color-swatch-wrapper{padding:0}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}::file-selector-button{font:inherit;-webkit-appearance:button}output{display:inline-block}iframe{border:0}summary{display:list-item;cursor:pointer}progress{vertical-align:baseline}[hidden]{display:none!important}.lead{font-size:1.25rem;font-weight:300}.display-1{font-size:calc(1.625rem + 4.5vw);font-weight:300;line-height:1.2}@media (min-width:1200px){.display-1{font-size:5rem}}.display-2{font-size:calc(1.575rem + 3.9vw);font-weight:300;line-height:1.2}@media (min-width:1200px){.display-2{font-size:4.5rem}}.display-3{font-size:calc(1.525rem + 3.3vw);font-weight:300;line-height:1.2}@media (min-width:1200px){.display-3{font-size:4rem}}.display-4{font-size:calc(1.475rem + 2.7vw);font-weight:300;line-height:1.2}@media (min-width:1200px){.display-4{font-size:3.5rem}}.display-5{font-size:calc(1.425rem + 2.1vw);font-weight:300;line-height:1.2}@media (min-width:1200px){.display-5{font-size:3rem}}.display-6{font-size:calc(1.375rem + 1.5vw);font-weight:300;line-height:1.2}@media (min-width:1200px){.display-6{font-size:2.5rem}}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-right:.5rem}.initialism{font-size:.875em;text-transform:uppercase}.blockquote{margin-bottom:1rem;font-size:1.25rem}.blockquote>:last-child{margin-bottom:0}.blockquote-footer{margin-top:-1rem;margin-bottom:1rem;font-size:.875em;color:#868e96}.blockquote-footer::before{content:"— "}.img-fluid{max-width:100%;height:auto}.img-thumbnail{padding:.25rem;background-color:var(--bs-body-bg);border:var(--bs-border-width) solid var(--bs-border-color);border-radius:var(--bs-border-radius);max-width:100%;height:auto}.figure{display:inline-block}.figure-img{margin-bottom:.5rem;line-height:1}.figure-caption{font-size:.875em;color:var(--bs-secondary-color)}.container,.container-fluid,.container-lg,.container-md,.container-sm,.container-xl,.container-xxl{--bs-gutter-x:1.5rem;--bs-gutter-y:0;width:100%;padding-right:calc(var(--bs-gutter-x) * .5);padding-left:calc(var(--bs-gutter-x) * .5);margin-right:auto;margin-left:auto}@media (min-width:576px){.container,.container-sm{max-width:540px}}@media (min-width:768px){.container,.container-md,.container-sm{max-width:720px}}@media (min-width:992px){.container,.container-lg,.container-md,.container-sm{max-width:960px}}@media (min-width:1200px){.container,.container-lg,.container-md,.container-sm,.container-xl{max-width:1140px}}@media (min-width:1400px){.container,.container-lg,.container-md,.container-sm,.container-xl,.container-xxl{max-width:1320px}}:root{--bs-breakpoint-xs:0;--bs-breakpoint-sm:576px;--bs-breakpoint-md:768px;--bs-breakpoint-lg:992px;--bs-breakpoint-xl:1200px;--bs-breakpoint-xxl:1400px}.row{--bs-gutter-x:1.5rem;--bs-gutter-y:0;display:flex;flex-wrap:wrap;margin-top:calc(-1 * var(--bs-gutter-y));margin-right:calc(-.5 * var(--bs-gutter-x));margin-left:calc(-.5 * var(--bs-gutter-x))}.row>*{flex-shrink:0;width:100%;max-width:100%;padding-right:calc(var(--bs-gutter-x) * .5);padding-left:calc(var(--bs-gutter-x) * .5);margin-top:var(--bs-gutter-y)}.col{flex:1 0 0%}.row-cols-auto>*{flex:0 0 auto;width:auto}.row-cols-1>*{flex:0 0 auto;width:100%}.row-cols-2>*{flex:0 0 auto;width:50%}.row-cols-3>*{flex:0 0 auto;width:33.33333333%}.row-cols-4>*{flex:0 0 auto;width:25%}.row-cols-5>*{flex:0 0 auto;width:20%}.row-cols-6>*{flex:0 0 auto;width:16.66666667%}.col-auto{flex:0 0 auto;width:auto}.col-1{flex:0 0 auto;width:8.33333333%}.col-2{flex:0 0 auto;width:16.66666667%}.col-3{flex:0 0 auto;width:25%}.col-4{flex:0 0 auto;width:33.33333333%}.col-5{flex:0 0 auto;width:41.66666667%}.col-6{flex:0 0 auto;width:50%}.col-7{flex:0 0 auto;width:58.33333333%}.col-8{flex:0 0 auto;width:66.66666667%}.col-9{flex:0 0 auto;width:75%}.col-10{flex:0 0 auto;width:83.33333333%}.col-11{flex:0 0 auto;width:91.66666667%}.col-12{flex:0 0 auto;width:100%}.offset-1{margin-left:8.33333333%}.offset-2{margin-left:16.66666667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.33333333%}.offset-5{margin-left:41.66666667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.33333333%}.offset-8{margin-left:66.66666667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.33333333%}.offset-11{margin-left:91.66666667%}.g-0,.gx-0{--bs-gutter-x:0}.g-0,.gy-0{--bs-gutter-y:0}.g-1,.gx-1{--bs-gutter-x:0.25rem}.g-1,.gy-1{--bs-gutter-y:0.25rem}.g-2,.gx-2{--bs-gutter-x:0.5rem}.g-2,.gy-2{--bs-gutter-y:0.5rem}.g-3,.gx-3{--bs-gutter-x:1rem}.g-3,.gy-3{--bs-gutter-y:1rem}.g-4,.gx-4{--bs-gutter-x:1.5rem}.g-4,.gy-4{--bs-gutter-y:1.5rem}.g-5,.gx-5{--bs-gutter-x:3rem}.g-5,.gy-5{--bs-gutter-y:3rem}@media (min-width:576px){.col-sm{flex:1 0 0%}.row-cols-sm-auto>*{flex:0 0 auto;width:auto}.row-cols-sm-1>*{flex:0 0 auto;width:100%}.row-cols-sm-2>*{flex:0 0 auto;width:50%}.row-cols-sm-3>*{flex:0 0 auto;width:33.33333333%}.row-cols-sm-4>*{flex:0 0 auto;width:25%}.row-cols-sm-5>*{flex:0 0 auto;width:20%}.row-cols-sm-6>*{flex:0 0 auto;width:16.66666667%}.col-sm-auto{flex:0 0 auto;width:auto}.col-sm-1{flex:0 0 auto;width:8.33333333%}.col-sm-2{flex:0 0 auto;width:16.66666667%}.col-sm-3{flex:0 0 auto;width:25%}.col-sm-4{flex:0 0 auto;width:33.33333333%}.col-sm-5{flex:0 0 auto;width:41.66666667%}.col-sm-6{flex:0 0 auto;width:50%}.col-sm-7{flex:0 0 auto;width:58.33333333%}.col-sm-8{flex:0 0 auto;width:66.66666667%}.col-sm-9{flex:0 0 auto;width:75%}.col-sm-10{flex:0 0 auto;width:83.33333333%}.col-sm-11{flex:0 0 auto;width:91.66666667%}.col-sm-12{flex:0 0 auto;width:100%}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.33333333%}.offset-sm-2{margin-left:16.66666667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.33333333%}.offset-sm-5{margin-left:41.66666667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.33333333%}.offset-sm-8{margin-left:66.66666667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.33333333%}.offset-sm-11{margin-left:91.66666667%}.g-sm-0,.gx-sm-0{--bs-gutter-x:0}.g-sm-0,.gy-sm-0{--bs-gutter-y:0}.g-sm-1,.gx-sm-1{--bs-gutter-x:0.25rem}.g-sm-1,.gy-sm-1{--bs-gutter-y:0.25rem}.g-sm-2,.gx-sm-2{--bs-gutter-x:0.5rem}.g-sm-2,.gy-sm-2{--bs-gutter-y:0.5rem}.g-sm-3,.gx-sm-3{--bs-gutter-x:1rem}.g-sm-3,.gy-sm-3{--bs-gutter-y:1rem}.g-sm-4,.gx-sm-4{--bs-gutter-x:1.5rem}.g-sm-4,.gy-sm-4{--bs-gutter-y:1.5rem}.g-sm-5,.gx-sm-5{--bs-gutter-x:3rem}.g-sm-5,.gy-sm-5{--bs-gutter-y:3rem}}@media (min-width:768px){.col-md{flex:1 0 0%}.row-cols-md-auto>*{flex:0 0 auto;width:auto}.row-cols-md-1>*{flex:0 0 auto;width:100%}.row-cols-md-2>*{flex:0 0 auto;width:50%}.row-cols-md-3>*{flex:0 0 auto;width:33.33333333%}.row-cols-md-4>*{flex:0 0 auto;width:25%}.row-cols-md-5>*{flex:0 0 auto;width:20%}.row-cols-md-6>*{flex:0 0 auto;width:16.66666667%}.col-md-auto{flex:0 0 auto;width:auto}.col-md-1{flex:0 0 auto;width:8.33333333%}.col-md-2{flex:0 0 auto;width:16.66666667%}.col-md-3{flex:0 0 auto;width:25%}.col-md-4{flex:0 0 auto;width:33.33333333%}.col-md-5{flex:0 0 auto;width:41.66666667%}.col-md-6{flex:0 0 auto;width:50%}.col-md-7{flex:0 0 auto;width:58.33333333%}.col-md-8{flex:0 0 auto;width:66.66666667%}.col-md-9{flex:0 0 auto;width:75%}.col-md-10{flex:0 0 auto;width:83.33333333%}.col-md-11{flex:0 0 auto;width:91.66666667%}.col-md-12{flex:0 0 auto;width:100%}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.33333333%}.offset-md-2{margin-left:16.66666667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.33333333%}.offset-md-5{margin-left:41.66666667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.33333333%}.offset-md-8{margin-left:66.66666667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.33333333%}.offset-md-11{margin-left:91.66666667%}.g-md-0,.gx-md-0{--bs-gutter-x:0}.g-md-0,.gy-md-0{--bs-gutter-y:0}.g-md-1,.gx-md-1{--bs-gutter-x:0.25rem}.g-md-1,.gy-md-1{--bs-gutter-y:0.25rem}.g-md-2,.gx-md-2{--bs-gutter-x:0.5rem}.g-md-2,.gy-md-2{--bs-gutter-y:0.5rem}.g-md-3,.gx-md-3{--bs-gutter-x:1rem}.g-md-3,.gy-md-3{--bs-gutter-y:1rem}.g-md-4,.gx-md-4{--bs-gutter-x:1.5rem}.g-md-4,.gy-md-4{--bs-gutter-y:1.5rem}.g-md-5,.gx-md-5{--bs-gutter-x:3rem}.g-md-5,.gy-md-5{--bs-gutter-y:3rem}}@media (min-width:992px){.col-lg{flex:1 0 0%}.row-cols-lg-auto>*{flex:0 0 auto;width:auto}.row-cols-lg-1>*{flex:0 0 auto;width:100%}.row-cols-lg-2>*{flex:0 0 auto;width:50%}.row-cols-lg-3>*{flex:0 0 auto;width:33.33333333%}.row-cols-lg-4>*{flex:0 0 auto;width:25%}.row-cols-lg-5>*{flex:0 0 auto;width:20%}.row-cols-lg-6>*{flex:0 0 auto;width:16.66666667%}.col-lg-auto{flex:0 0 auto;width:auto}.col-lg-1{flex:0 0 auto;width:8.33333333%}.col-lg-2{flex:0 0 auto;width:16.66666667%}.col-lg-3{flex:0 0 auto;width:25%}.col-lg-4{flex:0 0 auto;width:33.33333333%}.col-lg-5{flex:0 0 auto;width:41.66666667%}.col-lg-6{flex:0 0 auto;width:50%}.col-lg-7{flex:0 0 auto;width:58.33333333%}.col-lg-8{flex:0 0 auto;width:66.66666667%}.col-lg-9{flex:0 0 auto;width:75%}.col-lg-10{flex:0 0 auto;width:83.33333333%}.col-lg-11{flex:0 0 auto;width:91.66666667%}.col-lg-12{flex:0 0 auto;width:100%}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.33333333%}.offset-lg-2{margin-left:16.66666667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.33333333%}.offset-lg-5{margin-left:41.66666667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.33333333%}.offset-lg-8{margin-left:66.66666667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.33333333%}.offset-lg-11{margin-left:91.66666667%}.g-lg-0,.gx-lg-0{--bs-gutter-x:0}.g-lg-0,.gy-lg-0{--bs-gutter-y:0}.g-lg-1,.gx-lg-1{--bs-gutter-x:0.25rem}.g-lg-1,.gy-lg-1{--bs-gutter-y:0.25rem}.g-lg-2,.gx-lg-2{--bs-gutter-x:0.5rem}.g-lg-2,.gy-lg-2{--bs-gutter-y:0.5rem}.g-lg-3,.gx-lg-3{--bs-gutter-x:1rem}.g-lg-3,.gy-lg-3{--bs-gutter-y:1rem}.g-lg-4,.gx-lg-4{--bs-gutter-x:1.5rem}.g-lg-4,.gy-lg-4{--bs-gutter-y:1.5rem}.g-lg-5,.gx-lg-5{--bs-gutter-x:3rem}.g-lg-5,.gy-lg-5{--bs-gutter-y:3rem}}@media (min-width:1200px){.col-xl{flex:1 0 0%}.row-cols-xl-auto>*{flex:0 0 auto;width:auto}.row-cols-xl-1>*{flex:0 0 auto;width:100%}.row-cols-xl-2>*{flex:0 0 auto;width:50%}.row-cols-xl-3>*{flex:0 0 auto;width:33.33333333%}.row-cols-xl-4>*{flex:0 0 auto;width:25%}.row-cols-xl-5>*{flex:0 0 auto;width:20%}.row-cols-xl-6>*{flex:0 0 auto;width:16.66666667%}.col-xl-auto{flex:0 0 auto;width:auto}.col-xl-1{flex:0 0 auto;width:8.33333333%}.col-xl-2{flex:0 0 auto;width:16.66666667%}.col-xl-3{flex:0 0 auto;width:25%}.col-xl-4{flex:0 0 auto;width:33.33333333%}.col-xl-5{flex:0 0 auto;width:41.66666667%}.col-xl-6{flex:0 0 auto;width:50%}.col-xl-7{flex:0 0 auto;width:58.33333333%}.col-xl-8{flex:0 0 auto;width:66.66666667%}.col-xl-9{flex:0 0 auto;width:75%}.col-xl-10{flex:0 0 auto;width:83.33333333%}.col-xl-11{flex:0 0 auto;width:91.66666667%}.col-xl-12{flex:0 0 auto;width:100%}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.33333333%}.offset-xl-2{margin-left:16.66666667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.33333333%}.offset-xl-5{margin-left:41.66666667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.33333333%}.offset-xl-8{margin-left:66.66666667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.33333333%}.offset-xl-11{margin-left:91.66666667%}.g-xl-0,.gx-xl-0{--bs-gutter-x:0}.g-xl-0,.gy-xl-0{--bs-gutter-y:0}.g-xl-1,.gx-xl-1{--bs-gutter-x:0.25rem}.g-xl-1,.gy-xl-1{--bs-gutter-y:0.25rem}.g-xl-2,.gx-xl-2{--bs-gutter-x:0.5rem}.g-xl-2,.gy-xl-2{--bs-gutter-y:0.5rem}.g-xl-3,.gx-xl-3{--bs-gutter-x:1rem}.g-xl-3,.gy-xl-3{--bs-gutter-y:1rem}.g-xl-4,.gx-xl-4{--bs-gutter-x:1.5rem}.g-xl-4,.gy-xl-4{--bs-gutter-y:1.5rem}.g-xl-5,.gx-xl-5{--bs-gutter-x:3rem}.g-xl-5,.gy-xl-5{--bs-gutter-y:3rem}}@media (min-width:1400px){.col-xxl{flex:1 0 0%}.row-cols-xxl-auto>*{flex:0 0 auto;width:auto}.row-cols-xxl-1>*{flex:0 0 auto;width:100%}.row-cols-xxl-2>*{flex:0 0 auto;width:50%}.row-cols-xxl-3>*{flex:0 0 auto;width:33.33333333%}.row-cols-xxl-4>*{flex:0 0 auto;width:25%}.row-cols-xxl-5>*{flex:0 0 auto;width:20%}.row-cols-xxl-6>*{flex:0 0 auto;width:16.66666667%}.col-xxl-auto{flex:0 0 auto;width:auto}.col-xxl-1{flex:0 0 auto;width:8.33333333%}.col-xxl-2{flex:0 0 auto;width:16.66666667%}.col-xxl-3{flex:0 0 auto;width:25%}.col-xxl-4{flex:0 0 auto;width:33.33333333%}.col-xxl-5{flex:0 0 auto;width:41.66666667%}.col-xxl-6{flex:0 0 auto;width:50%}.col-xxl-7{flex:0 0 auto;width:58.33333333%}.col-xxl-8{flex:0 0 auto;width:66.66666667%}.col-xxl-9{flex:0 0 auto;width:75%}.col-xxl-10{flex:0 0 auto;width:83.33333333%}.col-xxl-11{flex:0 0 auto;width:91.66666667%}.col-xxl-12{flex:0 0 auto;width:100%}.offset-xxl-0{margin-left:0}.offset-xxl-1{margin-left:8.33333333%}.offset-xxl-2{margin-left:16.66666667%}.offset-xxl-3{margin-left:25%}.offset-xxl-4{margin-left:33.33333333%}.offset-xxl-5{margin-left:41.66666667%}.offset-xxl-6{margin-left:50%}.offset-xxl-7{margin-left:58.33333333%}.offset-xxl-8{margin-left:66.66666667%}.offset-xxl-9{margin-left:75%}.offset-xxl-10{margin-left:83.33333333%}.offset-xxl-11{margin-left:91.66666667%}.g-xxl-0,.gx-xxl-0{--bs-gutter-x:0}.g-xxl-0,.gy-xxl-0{--bs-gutter-y:0}.g-xxl-1,.gx-xxl-1{--bs-gutter-x:0.25rem}.g-xxl-1,.gy-xxl-1{--bs-gutter-y:0.25rem}.g-xxl-2,.gx-xxl-2{--bs-gutter-x:0.5rem}.g-xxl-2,.gy-xxl-2{--bs-gutter-y:0.5rem}.g-xxl-3,.gx-xxl-3{--bs-gutter-x:1rem}.g-xxl-3,.gy-xxl-3{--bs-gutter-y:1rem}.g-xxl-4,.gx-xxl-4{--bs-gutter-x:1.5rem}.g-xxl-4,.gy-xxl-4{--bs-gutter-y:1.5rem}.g-xxl-5,.gx-xxl-5{--bs-gutter-x:3rem}.g-xxl-5,.gy-xxl-5{--bs-gutter-y:3rem}}.table{--bs-table-color-type:initial;--bs-table-bg-type:initial;--bs-table-color-state:initial;--bs-table-bg-state:initial;--bs-table-color:var(--bs-emphasis-color);--bs-table-bg:var(--bs-body-bg);--bs-table-border-color:var(--bs-border-color);--bs-table-accent-bg:transparent;--bs-table-striped-color:var(--bs-emphasis-color);--bs-table-striped-bg:rgba(var(--bs-emphasis-color-rgb), 0.05);--bs-table-active-color:var(--bs-emphasis-color);--bs-table-active-bg:rgba(var(--bs-emphasis-color-rgb), 0.1);--bs-table-hover-color:var(--bs-emphasis-color);--bs-table-hover-bg:rgba(var(--bs-emphasis-color-rgb), 0.075);width:100%;margin-bottom:1rem;vertical-align:top;border-color:var(--bs-table-border-color)}.table>:not(caption)>*>*{padding:.5rem .5rem;color:var(--bs-table-color-state,var(--bs-table-color-type,var(--bs-table-color)));background-color:var(--bs-table-bg);border-bottom-width:var(--bs-border-width);box-shadow:inset 0 0 0 9999px var(--bs-table-bg-state,var(--bs-table-bg-type,var(--bs-table-accent-bg)))}.table>tbody{vertical-align:inherit}.table>thead{vertical-align:bottom}.table-group-divider{border-top:calc(var(--bs-border-width) * 2) solid currentcolor}.caption-top{caption-side:top}.table-sm>:not(caption)>*>*{padding:.25rem .25rem}.table-bordered>:not(caption)>*{border-width:var(--bs-border-width) 0}.table-bordered>:not(caption)>*>*{border-width:0 var(--bs-border-width)}.table-borderless>:not(caption)>*>*{border-bottom-width:0}.table-borderless>:not(:first-child){border-top-width:0}.table-striped>tbody>tr:nth-of-type(odd)>*{--bs-table-color-type:var(--bs-table-striped-color);--bs-table-bg-type:var(--bs-table-striped-bg)}.table-striped-columns>:not(caption)>tr>:nth-child(2n){--bs-table-color-type:var(--bs-table-striped-color);--bs-table-bg-type:var(--bs-table-striped-bg)}.table-active{--bs-table-color-state:var(--bs-table-active-color);--bs-table-bg-state:var(--bs-table-active-bg)}.table-hover>tbody>tr:hover>*{--bs-table-color-state:var(--bs-table-hover-color);--bs-table-bg-state:var(--bs-table-hover-bg)}.table-primary{--bs-table-color:#000;--bs-table-bg:#d5edfa;--bs-table-border-color:#aabec8;--bs-table-striped-bg:#cae1ee;--bs-table-striped-color:#000;--bs-table-active-bg:#c0d5e1;--bs-table-active-color:#000;--bs-table-hover-bg:#c5dbe7;--bs-table-hover-color:#000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-secondary{--bs-table-color:#000;--bs-table-bg:#fbfbfc;--bs-table-border-color:#c9c9ca;--bs-table-striped-bg:#eeeeef;--bs-table-striped-color:#000;--bs-table-active-bg:#e2e2e3;--bs-table-active-color:#000;--bs-table-hover-bg:#e8e8e9;--bs-table-hover-color:#000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-success{--bs-table-color:#000;--bs-table-bg:#e3eed7;--bs-table-border-color:#b6beac;--bs-table-striped-bg:#d8e2cc;--bs-table-striped-color:#000;--bs-table-active-bg:#ccd6c2;--bs-table-active-color:#000;--bs-table-hover-bg:#d2dcc7;--bs-table-hover-color:#000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-info{--bs-table-color:#000;--bs-table-bg:#cdd8e3;--bs-table-border-color:#a4adb6;--bs-table-striped-bg:#c3cdd8;--bs-table-striped-color:#000;--bs-table-active-bg:#b9c2cc;--bs-table-active-color:#000;--bs-table-hover-bg:#bec8d2;--bs-table-hover-color:#000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-warning{--bs-table-color:#000;--bs-table-bg:#f8ddcc;--bs-table-border-color:#c6b1a3;--bs-table-striped-bg:#ecd2c2;--bs-table-striped-color:#000;--bs-table-active-bg:#dfc7b8;--bs-table-active-color:#000;--bs-table-hover-bg:#e5ccbd;--bs-table-hover-color:#000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-danger{--bs-table-color:#000;--bs-table-bg:#f4d2d3;--bs-table-border-color:#c3a8a9;--bs-table-striped-bg:#e8c8c8;--bs-table-striped-color:#000;--bs-table-active-bg:#dcbdbe;--bs-table-active-color:#000;--bs-table-hover-bg:#e2c2c3;--bs-table-hover-color:#000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-light{--bs-table-color:#000;--bs-table-bg:#f8f9fa;--bs-table-border-color:#c6c7c8;--bs-table-striped-bg:#ecedee;--bs-table-striped-color:#000;--bs-table-active-bg:#dfe0e1;--bs-table-active-color:#000;--bs-table-hover-bg:#e5e6e7;--bs-table-hover-color:#000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-dark{--bs-table-color:#fff;--bs-table-bg:#343a40;--bs-table-border-color:#5d6166;--bs-table-striped-bg:#3e444a;--bs-table-striped-color:#fff;--bs-table-active-bg:#484e53;--bs-table-active-color:#fff;--bs-table-hover-bg:#43494e;--bs-table-hover-color:#fff;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-responsive{overflow-x:auto;-webkit-overflow-scrolling:touch}@media (max-width:575.98px){.table-responsive-sm{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media (max-width:767.98px){.table-responsive-md{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media (max-width:991.98px){.table-responsive-lg{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media (max-width:1199.98px){.table-responsive-xl{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media (max-width:1399.98px){.table-responsive-xxl{overflow-x:auto;-webkit-overflow-scrolling:touch}}.form-label{margin-bottom:.5rem}.col-form-label{padding-top:calc(.375rem + var(--bs-border-width));padding-bottom:calc(.375rem + var(--bs-border-width));margin-bottom:0;font-size:inherit;line-height:1.5}.col-form-label-lg{padding-top:calc(.5rem + var(--bs-border-width));padding-bottom:calc(.5rem + var(--bs-border-width));font-size:1.25rem}.col-form-label-sm{padding-top:calc(.25rem + var(--bs-border-width));padding-bottom:calc(.25rem + var(--bs-border-width));font-size:.875rem}.form-text{margin-top:.25rem;font-size:.875em;color:var(--bs-secondary-color)}.form-control{display:block;width:100%;padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:var(--bs-body-color);-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:var(--bs-body-bg);background-clip:padding-box;border:var(--bs-border-width) solid var(--bs-border-color);border-radius:var(--bs-border-radius);transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-control{transition:none}}.form-control[type=file]{overflow:hidden}.form-control[type=file]:not(:disabled):not([readonly]){cursor:pointer}.form-control:focus{color:var(--bs-body-color);background-color:var(--bs-body-bg);border-color:#97d2f3;outline:0;box-shadow:0 0 0 .25rem rgba(47,164,231,.25)}.form-control::-webkit-date-and-time-value{min-width:85px;height:1.5em;margin:0}.form-control::-webkit-datetime-edit{display:block;padding:0}.form-control::-moz-placeholder{color:var(--bs-secondary-color);opacity:1}.form-control::placeholder{color:var(--bs-secondary-color);opacity:1}.form-control:disabled{background-color:var(--bs-secondary-bg);opacity:1}.form-control::-webkit-file-upload-button{padding:.375rem .75rem;margin:-.375rem -.75rem;-webkit-margin-end:.75rem;margin-inline-end:.75rem;color:var(--bs-body-color);background-color:var(--bs-tertiary-bg);pointer-events:none;border-color:inherit;border-style:solid;border-width:0;border-inline-end-width:var(--bs-border-width);border-radius:0;-webkit-transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}.form-control::file-selector-button{padding:.375rem .75rem;margin:-.375rem -.75rem;-webkit-margin-end:.75rem;margin-inline-end:.75rem;color:var(--bs-body-color);background-color:var(--bs-tertiary-bg);pointer-events:none;border-color:inherit;border-style:solid;border-width:0;border-inline-end-width:var(--bs-border-width);border-radius:0;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-control::-webkit-file-upload-button{-webkit-transition:none;transition:none}.form-control::file-selector-button{transition:none}}.form-control:hover:not(:disabled):not([readonly])::-webkit-file-upload-button{background-color:var(--bs-secondary-bg)}.form-control:hover:not(:disabled):not([readonly])::file-selector-button{background-color:var(--bs-secondary-bg)}.form-control-plaintext{display:block;width:100%;padding:.375rem 0;margin-bottom:0;line-height:1.5;color:var(--bs-body-color);background-color:transparent;border:solid transparent;border-width:var(--bs-border-width) 0}.form-control-plaintext:focus{outline:0}.form-control-plaintext.form-control-lg,.form-control-plaintext.form-control-sm{padding-right:0;padding-left:0}.form-control-sm{min-height:calc(1.5em + .5rem + calc(var(--bs-border-width) * 2));padding:.25rem .5rem;font-size:.875rem;border-radius:var(--bs-border-radius-sm)}.form-control-sm::-webkit-file-upload-button{padding:.25rem .5rem;margin:-.25rem -.5rem;-webkit-margin-end:.5rem;margin-inline-end:.5rem}.form-control-sm::file-selector-button{padding:.25rem .5rem;margin:-.25rem -.5rem;-webkit-margin-end:.5rem;margin-inline-end:.5rem}.form-control-lg{min-height:calc(1.5em + 1rem + calc(var(--bs-border-width) * 2));padding:.5rem 1rem;font-size:1.25rem;border-radius:var(--bs-border-radius-lg)}.form-control-lg::-webkit-file-upload-button{padding:.5rem 1rem;margin:-.5rem -1rem;-webkit-margin-end:1rem;margin-inline-end:1rem}.form-control-lg::file-selector-button{padding:.5rem 1rem;margin:-.5rem -1rem;-webkit-margin-end:1rem;margin-inline-end:1rem}textarea.form-control{min-height:calc(1.5em + .75rem + calc(var(--bs-border-width) * 2))}textarea.form-control-sm{min-height:calc(1.5em + .5rem + calc(var(--bs-border-width) * 2))}textarea.form-control-lg{min-height:calc(1.5em + 1rem + calc(var(--bs-border-width) * 2))}.form-control-color{width:3rem;height:calc(1.5em + .75rem + calc(var(--bs-border-width) * 2));padding:.375rem}.form-control-color:not(:disabled):not([readonly]){cursor:pointer}.form-control-color::-moz-color-swatch{border:0!important;border-radius:var(--bs-border-radius)}.form-control-color::-webkit-color-swatch{border:0!important;border-radius:var(--bs-border-radius)}.form-control-color.form-control-sm{height:calc(1.5em + .5rem + calc(var(--bs-border-width) * 2))}.form-control-color.form-control-lg{height:calc(1.5em + 1rem + calc(var(--bs-border-width) * 2))}.form-select{--bs-form-select-bg-img:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e");display:block;width:100%;padding:.375rem 2.25rem .375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:var(--bs-body-color);-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:var(--bs-body-bg);background-image:var(--bs-form-select-bg-img),var(--bs-form-select-bg-icon,none);background-repeat:no-repeat;background-position:right .75rem center;background-size:16px 12px;border:var(--bs-border-width) solid var(--bs-border-color);border-radius:var(--bs-border-radius);transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-select{transition:none}}.form-select:focus{border-color:#97d2f3;outline:0;box-shadow:0 0 0 .25rem rgba(47,164,231,.25)}.form-select[multiple],.form-select[size]:not([size="1"]){padding-right:.75rem;background-image:none}.form-select:disabled{background-color:var(--bs-secondary-bg)}.form-select:-moz-focusring{color:transparent;text-shadow:0 0 0 var(--bs-body-color)}.form-select-sm{padding-top:.25rem;padding-bottom:.25rem;padding-left:.5rem;font-size:.875rem;border-radius:var(--bs-border-radius-sm)}.form-select-lg{padding-top:.5rem;padding-bottom:.5rem;padding-left:1rem;font-size:1.25rem;border-radius:var(--bs-border-radius-lg)}[data-bs-theme=dark] .form-select{--bs-form-select-bg-img:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23dee2e6' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e")}.form-check{display:block;min-height:1.5rem;padding-left:1.5em;margin-bottom:.125rem}.form-check .form-check-input{float:left;margin-left:-1.5em}.form-check-reverse{padding-right:1.5em;padding-left:0;text-align:right}.form-check-reverse .form-check-input{float:right;margin-right:-1.5em;margin-left:0}.form-check-input{--bs-form-check-bg:var(--bs-body-bg);flex-shrink:0;width:1em;height:1em;margin-top:.25em;vertical-align:top;-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:var(--bs-form-check-bg);background-image:var(--bs-form-check-bg-image);background-repeat:no-repeat;background-position:center;background-size:contain;border:var(--bs-border-width) solid var(--bs-border-color);-webkit-print-color-adjust:exact;color-adjust:exact;print-color-adjust:exact}.form-check-input[type=checkbox]{border-radius:.25em}.form-check-input[type=radio]{border-radius:50%}.form-check-input:active{filter:brightness(90%)}.form-check-input:focus{border-color:#97d2f3;outline:0;box-shadow:0 0 0 .25rem rgba(47,164,231,.25)}.form-check-input:checked{background-color:#2fa4e7;border-color:#2fa4e7}.form-check-input:checked[type=checkbox]{--bs-form-check-bg-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='m6 10 3 3 6-6'/%3e%3c/svg%3e")}.form-check-input:checked[type=radio]{--bs-form-check-bg-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='2' fill='%23fff'/%3e%3c/svg%3e")}.form-check-input[type=checkbox]:indeterminate{background-color:#2fa4e7;border-color:#2fa4e7;--bs-form-check-bg-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10h8'/%3e%3c/svg%3e")}.form-check-input:disabled{pointer-events:none;filter:none;opacity:.5}.form-check-input:disabled~.form-check-label,.form-check-input[disabled]~.form-check-label{cursor:default;opacity:.5}.form-switch{padding-left:2.5em}.form-switch .form-check-input{--bs-form-switch-bg:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba%280, 0, 0, 0.25%29'/%3e%3c/svg%3e");width:2em;margin-left:-2.5em;background-image:var(--bs-form-switch-bg);background-position:left center;border-radius:2em;transition:background-position .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-switch .form-check-input{transition:none}}.form-switch .form-check-input:focus{--bs-form-switch-bg:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%2397d2f3'/%3e%3c/svg%3e")}.form-switch .form-check-input:checked{background-position:right center;--bs-form-switch-bg:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e")}.form-switch.form-check-reverse{padding-right:2.5em;padding-left:0}.form-switch.form-check-reverse .form-check-input{margin-right:-2.5em;margin-left:0}.form-check-inline{display:inline-block;margin-right:1rem}.btn-check{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.btn-check:disabled+.btn,.btn-check[disabled]+.btn{pointer-events:none;filter:none;opacity:.65}[data-bs-theme=dark] .form-switch .form-check-input:not(:checked):not(:focus){--bs-form-switch-bg:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba%28255, 255, 255, 0.25%29'/%3e%3c/svg%3e")}.form-range{width:100%;height:1.5rem;padding:0;-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:transparent}.form-range:focus{outline:0}.form-range:focus::-webkit-slider-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .25rem rgba(47,164,231,.25)}.form-range:focus::-moz-range-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .25rem rgba(47,164,231,.25)}.form-range::-moz-focus-outer{border:0}.form-range::-webkit-slider-thumb{width:1rem;height:1rem;margin-top:-.25rem;-webkit-appearance:none;appearance:none;background-color:#2fa4e7;border:0;border-radius:1rem;-webkit-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-range::-webkit-slider-thumb{-webkit-transition:none;transition:none}}.form-range::-webkit-slider-thumb:active{background-color:#c1e4f8}.form-range::-webkit-slider-runnable-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:var(--bs-secondary-bg);border-color:transparent;border-radius:1rem}.form-range::-moz-range-thumb{width:1rem;height:1rem;-moz-appearance:none;appearance:none;background-color:#2fa4e7;border:0;border-radius:1rem;-moz-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-range::-moz-range-thumb{-moz-transition:none;transition:none}}.form-range::-moz-range-thumb:active{background-color:#c1e4f8}.form-range::-moz-range-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:var(--bs-secondary-bg);border-color:transparent;border-radius:1rem}.form-range:disabled{pointer-events:none}.form-range:disabled::-webkit-slider-thumb{background-color:var(--bs-secondary-color)}.form-range:disabled::-moz-range-thumb{background-color:var(--bs-secondary-color)}.form-floating{position:relative}.form-floating>.form-control,.form-floating>.form-control-plaintext,.form-floating>.form-select{height:calc(3.5rem + calc(var(--bs-border-width) * 2));min-height:calc(3.5rem + calc(var(--bs-border-width) * 2));line-height:1.25}.form-floating>label{position:absolute;top:0;left:0;z-index:2;height:100%;padding:1rem .75rem;overflow:hidden;text-align:start;text-overflow:ellipsis;white-space:nowrap;pointer-events:none;border:var(--bs-border-width) solid transparent;transform-origin:0 0;transition:opacity .1s ease-in-out,transform .1s ease-in-out}@media (prefers-reduced-motion:reduce){.form-floating>label{transition:none}}.form-floating>.form-control,.form-floating>.form-control-plaintext{padding:1rem .75rem}.form-floating>.form-control-plaintext::-moz-placeholder,.form-floating>.form-control::-moz-placeholder{color:transparent}.form-floating>.form-control-plaintext::placeholder,.form-floating>.form-control::placeholder{color:transparent}.form-floating>.form-control-plaintext:not(:-moz-placeholder-shown),.form-floating>.form-control:not(:-moz-placeholder-shown){padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-control-plaintext:focus,.form-floating>.form-control-plaintext:not(:placeholder-shown),.form-floating>.form-control:focus,.form-floating>.form-control:not(:placeholder-shown){padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-control-plaintext:-webkit-autofill,.form-floating>.form-control:-webkit-autofill{padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-select{padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-control:not(:-moz-placeholder-shown)~label{color:rgba(var(--bs-body-color-rgb),.65);transform:scale(.85) translateY(-.5rem) translateX(.15rem)}.form-floating>.form-control-plaintext~label,.form-floating>.form-control:focus~label,.form-floating>.form-control:not(:placeholder-shown)~label,.form-floating>.form-select~label{color:rgba(var(--bs-body-color-rgb),.65);transform:scale(.85) translateY(-.5rem) translateX(.15rem)}.form-floating>.form-control:not(:-moz-placeholder-shown)~label::after{position:absolute;inset:1rem 0.375rem;z-index:-1;height:1.5em;content:"";background-color:var(--bs-body-bg);border-radius:var(--bs-border-radius)}.form-floating>.form-control-plaintext~label::after,.form-floating>.form-control:focus~label::after,.form-floating>.form-control:not(:placeholder-shown)~label::after,.form-floating>.form-select~label::after{position:absolute;inset:1rem 0.375rem;z-index:-1;height:1.5em;content:"";background-color:var(--bs-body-bg);border-radius:var(--bs-border-radius)}.form-floating>.form-control:-webkit-autofill~label{color:rgba(var(--bs-body-color-rgb),.65);transform:scale(.85) translateY(-.5rem) translateX(.15rem)}.form-floating>.form-control-plaintext~label{border-width:var(--bs-border-width) 0}.form-floating>.form-control:disabled~label,.form-floating>:disabled~label{color:#868e96}.form-floating>.form-control:disabled~label::after,.form-floating>:disabled~label::after{background-color:var(--bs-secondary-bg)}.input-group{position:relative;display:flex;flex-wrap:wrap;align-items:stretch;width:100%}.input-group>.form-control,.input-group>.form-floating,.input-group>.form-select{position:relative;flex:1 1 auto;width:1%;min-width:0}.input-group>.form-control:focus,.input-group>.form-floating:focus-within,.input-group>.form-select:focus{z-index:5}.input-group .btn{position:relative;z-index:2}.input-group .btn:focus{z-index:5}.input-group-text{display:flex;align-items:center;padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:var(--bs-body-color);text-align:center;white-space:nowrap;background-color:var(--bs-tertiary-bg);border:var(--bs-border-width) solid var(--bs-border-color);border-radius:var(--bs-border-radius)}.input-group-lg>.btn,.input-group-lg>.form-control,.input-group-lg>.form-select,.input-group-lg>.input-group-text{padding:.5rem 1rem;font-size:1.25rem;border-radius:var(--bs-border-radius-lg)}.input-group-sm>.btn,.input-group-sm>.form-control,.input-group-sm>.form-select,.input-group-sm>.input-group-text{padding:.25rem .5rem;font-size:.875rem;border-radius:var(--bs-border-radius-sm)}.input-group-lg>.form-select,.input-group-sm>.form-select{padding-right:3rem}.input-group:not(.has-validation)>.dropdown-toggle:nth-last-child(n+3),.input-group:not(.has-validation)>.form-floating:not(:last-child)>.form-control,.input-group:not(.has-validation)>.form-floating:not(:last-child)>.form-select,.input-group:not(.has-validation)>:not(:last-child):not(.dropdown-toggle):not(.dropdown-menu):not(.form-floating){border-top-right-radius:0;border-bottom-right-radius:0}.input-group.has-validation>.dropdown-toggle:nth-last-child(n+4),.input-group.has-validation>.form-floating:nth-last-child(n+3)>.form-control,.input-group.has-validation>.form-floating:nth-last-child(n+3)>.form-select,.input-group.has-validation>:nth-last-child(n+3):not(.dropdown-toggle):not(.dropdown-menu):not(.form-floating){border-top-right-radius:0;border-bottom-right-radius:0}.input-group>:not(:first-child):not(.dropdown-menu):not(.valid-tooltip):not(.valid-feedback):not(.invalid-tooltip):not(.invalid-feedback){margin-left:calc(var(--bs-border-width) * -1);border-top-left-radius:0;border-bottom-left-radius:0}.input-group>.form-floating:not(:first-child)>.form-control,.input-group>.form-floating:not(:first-child)>.form-select{border-top-left-radius:0;border-bottom-left-radius:0}.valid-feedback{display:none;width:100%;margin-top:.25rem;font-size:.875em;color:var(--bs-form-valid-color)}.valid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;color:#fff;background-color:var(--bs-success);border-radius:var(--bs-border-radius)}.is-valid~.valid-feedback,.is-valid~.valid-tooltip,.was-validated :valid~.valid-feedback,.was-validated :valid~.valid-tooltip{display:block}.form-control.is-valid,.was-validated .form-control:valid{border-color:var(--bs-form-valid-border-color);padding-right:calc(1.5em + .75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%2373a839' d='M2.3 6.73.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(.375em + .1875rem) center;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.form-control.is-valid:focus,.was-validated .form-control:valid:focus{border-color:var(--bs-form-valid-border-color);box-shadow:0 0 0 .25rem rgba(var(--bs-success-rgb),.25)}.was-validated textarea.form-control:valid,textarea.form-control.is-valid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.form-select.is-valid,.was-validated .form-select:valid{border-color:var(--bs-form-valid-border-color)}.form-select.is-valid:not([multiple]):not([size]),.form-select.is-valid:not([multiple])[size="1"],.was-validated .form-select:valid:not([multiple]):not([size]),.was-validated .form-select:valid:not([multiple])[size="1"]{--bs-form-select-bg-icon:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%2373a839' d='M2.3 6.73.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e");padding-right:4.125rem;background-position:right .75rem center,center right 2.25rem;background-size:16px 12px,calc(.75em + .375rem) calc(.75em + .375rem)}.form-select.is-valid:focus,.was-validated .form-select:valid:focus{border-color:var(--bs-form-valid-border-color);box-shadow:0 0 0 .25rem rgba(var(--bs-success-rgb),.25)}.form-control-color.is-valid,.was-validated .form-control-color:valid{width:calc(3rem + calc(1.5em + .75rem))}.form-check-input.is-valid,.was-validated .form-check-input:valid{border-color:var(--bs-form-valid-border-color)}.form-check-input.is-valid:checked,.was-validated .form-check-input:valid:checked{background-color:var(--bs-form-valid-color)}.form-check-input.is-valid:focus,.was-validated .form-check-input:valid:focus{box-shadow:0 0 0 .25rem rgba(var(--bs-success-rgb),.25)}.form-check-input.is-valid~.form-check-label,.was-validated .form-check-input:valid~.form-check-label{color:var(--bs-form-valid-color)}.form-check-inline .form-check-input~.valid-feedback{margin-left:.5em}.input-group>.form-control:not(:focus).is-valid,.input-group>.form-floating:not(:focus-within).is-valid,.input-group>.form-select:not(:focus).is-valid,.was-validated .input-group>.form-control:not(:focus):valid,.was-validated .input-group>.form-floating:not(:focus-within):valid,.was-validated .input-group>.form-select:not(:focus):valid{z-index:3}.invalid-feedback{display:none;width:100%;margin-top:.25rem;font-size:.875em;color:var(--bs-form-invalid-color)}.invalid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;color:#fff;background-color:var(--bs-danger);border-radius:var(--bs-border-radius)}.is-invalid~.invalid-feedback,.is-invalid~.invalid-tooltip,.was-validated :invalid~.invalid-feedback,.was-validated :invalid~.invalid-tooltip{display:block}.form-control.is-invalid,.was-validated .form-control:invalid{border-color:var(--bs-form-invalid-border-color);padding-right:calc(1.5em + .75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23c71c22'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23c71c22' stroke='none'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(.375em + .1875rem) center;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.form-control.is-invalid:focus,.was-validated .form-control:invalid:focus{border-color:var(--bs-form-invalid-border-color);box-shadow:0 0 0 .25rem rgba(var(--bs-danger-rgb),.25)}.was-validated textarea.form-control:invalid,textarea.form-control.is-invalid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.form-select.is-invalid,.was-validated .form-select:invalid{border-color:var(--bs-form-invalid-border-color)}.form-select.is-invalid:not([multiple]):not([size]),.form-select.is-invalid:not([multiple])[size="1"],.was-validated .form-select:invalid:not([multiple]):not([size]),.was-validated .form-select:invalid:not([multiple])[size="1"]{--bs-form-select-bg-icon:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23c71c22'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23c71c22' stroke='none'/%3e%3c/svg%3e");padding-right:4.125rem;background-position:right .75rem center,center right 2.25rem;background-size:16px 12px,calc(.75em + .375rem) calc(.75em + .375rem)}.form-select.is-invalid:focus,.was-validated .form-select:invalid:focus{border-color:var(--bs-form-invalid-border-color);box-shadow:0 0 0 .25rem rgba(var(--bs-danger-rgb),.25)}.form-control-color.is-invalid,.was-validated .form-control-color:invalid{width:calc(3rem + calc(1.5em + .75rem))}.form-check-input.is-invalid,.was-validated .form-check-input:invalid{border-color:var(--bs-form-invalid-border-color)}.form-check-input.is-invalid:checked,.was-validated .form-check-input:invalid:checked{background-color:var(--bs-form-invalid-color)}.form-check-input.is-invalid:focus,.was-validated .form-check-input:invalid:focus{box-shadow:0 0 0 .25rem rgba(var(--bs-danger-rgb),.25)}.form-check-input.is-invalid~.form-check-label,.was-validated .form-check-input:invalid~.form-check-label{color:var(--bs-form-invalid-color)}.form-check-inline .form-check-input~.invalid-feedback{margin-left:.5em}.input-group>.form-control:not(:focus).is-invalid,.input-group>.form-floating:not(:focus-within).is-invalid,.input-group>.form-select:not(:focus).is-invalid,.was-validated .input-group>.form-control:not(:focus):invalid,.was-validated .input-group>.form-floating:not(:focus-within):invalid,.was-validated .input-group>.form-select:not(:focus):invalid{z-index:4}.btn{--bs-btn-padding-x:0.75rem;--bs-btn-padding-y:0.375rem;--bs-btn-font-family: ;--bs-btn-font-size:1rem;--bs-btn-font-weight:400;--bs-btn-line-height:1.5;--bs-btn-color:var(--bs-body-color);--bs-btn-bg:transparent;--bs-btn-border-width:var(--bs-border-width);--bs-btn-border-color:transparent;--bs-btn-border-radius:var(--bs-border-radius);--bs-btn-hover-border-color:transparent;--bs-btn-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.15),0 1px 1px rgba(0, 0, 0, 0.075);--bs-btn-disabled-opacity:0.65;--bs-btn-focus-box-shadow:0 0 0 0.25rem rgba(var(--bs-btn-focus-shadow-rgb), .5);display:inline-block;padding:var(--bs-btn-padding-y) var(--bs-btn-padding-x);font-family:var(--bs-btn-font-family);font-size:var(--bs-btn-font-size);font-weight:var(--bs-btn-font-weight);line-height:var(--bs-btn-line-height);color:var(--bs-btn-color);text-align:center;text-decoration:none;vertical-align:middle;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;user-select:none;border:var(--bs-btn-border-width) solid var(--bs-btn-border-color);border-radius:var(--bs-btn-border-radius);background-color:var(--bs-btn-bg);transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.btn{transition:none}}.btn:hover{color:var(--bs-btn-hover-color);background-color:var(--bs-btn-hover-bg);border-color:var(--bs-btn-hover-border-color)}.btn-check+.btn:hover{color:var(--bs-btn-color);background-color:var(--bs-btn-bg);border-color:var(--bs-btn-border-color)}.btn:focus-visible{color:var(--bs-btn-hover-color);background-color:var(--bs-btn-hover-bg);border-color:var(--bs-btn-hover-border-color);outline:0;box-shadow:var(--bs-btn-focus-box-shadow)}.btn-check:focus-visible+.btn{border-color:var(--bs-btn-hover-border-color);outline:0;box-shadow:var(--bs-btn-focus-box-shadow)}.btn-check:checked+.btn,.btn.active,.btn.show,.btn:first-child:active,:not(.btn-check)+.btn:active{color:var(--bs-btn-active-color);background-color:var(--bs-btn-active-bg);border-color:var(--bs-btn-active-border-color)}.btn-check:checked+.btn:focus-visible,.btn.active:focus-visible,.btn.show:focus-visible,.btn:first-child:active:focus-visible,:not(.btn-check)+.btn:active:focus-visible{box-shadow:var(--bs-btn-focus-box-shadow)}.btn.disabled,.btn:disabled,fieldset:disabled .btn{color:var(--bs-btn-disabled-color);pointer-events:none;background-color:var(--bs-btn-disabled-bg);border-color:var(--bs-btn-disabled-border-color);opacity:var(--bs-btn-disabled-opacity)}.btn-primary{--bs-btn-color:#fff;--bs-btn-bg:#2fa4e7;--bs-btn-border-color:#2fa4e7;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#288bc4;--bs-btn-hover-border-color:#2683b9;--bs-btn-focus-shadow-rgb:78,178,235;--bs-btn-active-color:#fff;--bs-btn-active-bg:#2683b9;--bs-btn-active-border-color:#237bad;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#fff;--bs-btn-disabled-bg:#2fa4e7;--bs-btn-disabled-border-color:#2fa4e7}.btn-secondary{--bs-btn-color:#000;--bs-btn-bg:#e9ecef;--bs-btn-border-color:#e9ecef;--bs-btn-hover-color:#000;--bs-btn-hover-bg:#eceff1;--bs-btn-hover-border-color:#ebeef1;--bs-btn-focus-shadow-rgb:198,201,203;--bs-btn-active-color:#000;--bs-btn-active-bg:#edf0f2;--bs-btn-active-border-color:#ebeef1;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#000;--bs-btn-disabled-bg:#e9ecef;--bs-btn-disabled-border-color:#e9ecef}.btn-success{--bs-btn-color:#fff;--bs-btn-bg:#73a839;--bs-btn-border-color:#73a839;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#628f30;--bs-btn-hover-border-color:#5c862e;--bs-btn-focus-shadow-rgb:136,181,87;--bs-btn-active-color:#fff;--bs-btn-active-bg:#5c862e;--bs-btn-active-border-color:#567e2b;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#fff;--bs-btn-disabled-bg:#73a839;--bs-btn-disabled-border-color:#73a839}.btn-info{--bs-btn-color:#fff;--bs-btn-bg:#033c73;--bs-btn-border-color:#033c73;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#033362;--bs-btn-hover-border-color:#02305c;--bs-btn-focus-shadow-rgb:41,89,136;--bs-btn-active-color:#fff;--bs-btn-active-bg:#02305c;--bs-btn-active-border-color:#022d56;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#fff;--bs-btn-disabled-bg:#033c73;--bs-btn-disabled-border-color:#033c73}.btn-warning{--bs-btn-color:#fff;--bs-btn-bg:#dd5600;--bs-btn-border-color:#dd5600;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#bc4900;--bs-btn-hover-border-color:#b14500;--bs-btn-focus-shadow-rgb:226,111,38;--bs-btn-active-color:#fff;--bs-btn-active-bg:#b14500;--bs-btn-active-border-color:#a64100;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#fff;--bs-btn-disabled-bg:#dd5600;--bs-btn-disabled-border-color:#dd5600}.btn-danger{--bs-btn-color:#fff;--bs-btn-bg:#c71c22;--bs-btn-border-color:#c71c22;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#a9181d;--bs-btn-hover-border-color:#9f161b;--bs-btn-focus-shadow-rgb:207,62,67;--bs-btn-active-color:#fff;--bs-btn-active-bg:#9f161b;--bs-btn-active-border-color:#95151a;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#fff;--bs-btn-disabled-bg:#c71c22;--bs-btn-disabled-border-color:#c71c22}.btn-light{--bs-btn-color:#000;--bs-btn-bg:#f8f9fa;--bs-btn-border-color:#f8f9fa;--bs-btn-hover-color:#000;--bs-btn-hover-bg:#d3d4d5;--bs-btn-hover-border-color:#c6c7c8;--bs-btn-focus-shadow-rgb:211,212,213;--bs-btn-active-color:#000;--bs-btn-active-bg:#c6c7c8;--bs-btn-active-border-color:#babbbc;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#000;--bs-btn-disabled-bg:#f8f9fa;--bs-btn-disabled-border-color:#f8f9fa}.btn-dark{--bs-btn-color:#fff;--bs-btn-bg:#343a40;--bs-btn-border-color:#343a40;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#52585d;--bs-btn-hover-border-color:#484e53;--bs-btn-focus-shadow-rgb:82,88,93;--bs-btn-active-color:#fff;--bs-btn-active-bg:#5d6166;--bs-btn-active-border-color:#484e53;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#fff;--bs-btn-disabled-bg:#343a40;--bs-btn-disabled-border-color:#343a40}.btn-outline-primary{--bs-btn-color:#2fa4e7;--bs-btn-border-color:#2fa4e7;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#2fa4e7;--bs-btn-hover-border-color:#2fa4e7;--bs-btn-focus-shadow-rgb:47,164,231;--bs-btn-active-color:#fff;--bs-btn-active-bg:#2fa4e7;--bs-btn-active-border-color:#2fa4e7;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#2fa4e7;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#2fa4e7;--bs-gradient:none}.btn-outline-secondary{--bs-btn-color:#e9ecef;--bs-btn-border-color:#e9ecef;--bs-btn-hover-color:#000;--bs-btn-hover-bg:#e9ecef;--bs-btn-hover-border-color:#e9ecef;--bs-btn-focus-shadow-rgb:233,236,239;--bs-btn-active-color:#000;--bs-btn-active-bg:#e9ecef;--bs-btn-active-border-color:#e9ecef;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#e9ecef;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#e9ecef;--bs-gradient:none}.btn-outline-success{--bs-btn-color:#73a839;--bs-btn-border-color:#73a839;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#73a839;--bs-btn-hover-border-color:#73a839;--bs-btn-focus-shadow-rgb:115,168,57;--bs-btn-active-color:#fff;--bs-btn-active-bg:#73a839;--bs-btn-active-border-color:#73a839;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#73a839;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#73a839;--bs-gradient:none}.btn-outline-info{--bs-btn-color:#033c73;--bs-btn-border-color:#033c73;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#033c73;--bs-btn-hover-border-color:#033c73;--bs-btn-focus-shadow-rgb:3,60,115;--bs-btn-active-color:#fff;--bs-btn-active-bg:#033c73;--bs-btn-active-border-color:#033c73;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#033c73;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#033c73;--bs-gradient:none}.btn-outline-warning{--bs-btn-color:#dd5600;--bs-btn-border-color:#dd5600;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#dd5600;--bs-btn-hover-border-color:#dd5600;--bs-btn-focus-shadow-rgb:221,86,0;--bs-btn-active-color:#fff;--bs-btn-active-bg:#dd5600;--bs-btn-active-border-color:#dd5600;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#dd5600;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#dd5600;--bs-gradient:none}.btn-outline-danger{--bs-btn-color:#c71c22;--bs-btn-border-color:#c71c22;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#c71c22;--bs-btn-hover-border-color:#c71c22;--bs-btn-focus-shadow-rgb:199,28,34;--bs-btn-active-color:#fff;--bs-btn-active-bg:#c71c22;--bs-btn-active-border-color:#c71c22;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#c71c22;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#c71c22;--bs-gradient:none}.btn-outline-light{--bs-btn-color:#f8f9fa;--bs-btn-border-color:#f8f9fa;--bs-btn-hover-color:#000;--bs-btn-hover-bg:#f8f9fa;--bs-btn-hover-border-color:#f8f9fa;--bs-btn-focus-shadow-rgb:248,249,250;--bs-btn-active-color:#000;--bs-btn-active-bg:#f8f9fa;--bs-btn-active-border-color:#f8f9fa;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#f8f9fa;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#f8f9fa;--bs-gradient:none}.btn-outline-dark{--bs-btn-color:#343a40;--bs-btn-border-color:#343a40;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#343a40;--bs-btn-hover-border-color:#343a40;--bs-btn-focus-shadow-rgb:52,58,64;--bs-btn-active-color:#fff;--bs-btn-active-bg:#343a40;--bs-btn-active-border-color:#343a40;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#343a40;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#343a40;--bs-gradient:none}.btn-link{--bs-btn-font-weight:400;--bs-btn-color:var(--bs-link-color);--bs-btn-bg:transparent;--bs-btn-border-color:transparent;--bs-btn-hover-color:var(--bs-link-hover-color);--bs-btn-hover-border-color:transparent;--bs-btn-active-color:var(--bs-link-hover-color);--bs-btn-active-border-color:transparent;--bs-btn-disabled-color:#868e96;--bs-btn-disabled-border-color:transparent;--bs-btn-box-shadow:0 0 0 #000;--bs-btn-focus-shadow-rgb:78,178,235;text-decoration:underline}.btn-link:focus-visible{color:var(--bs-btn-color)}.btn-link:hover{color:var(--bs-btn-hover-color)}.btn-group-lg>.btn,.btn-lg{--bs-btn-padding-y:0.5rem;--bs-btn-padding-x:1rem;--bs-btn-font-size:1.25rem;--bs-btn-border-radius:var(--bs-border-radius-lg)}.btn-group-sm>.btn,.btn-sm{--bs-btn-padding-y:0.25rem;--bs-btn-padding-x:0.5rem;--bs-btn-font-size:0.875rem;--bs-btn-border-radius:var(--bs-border-radius-sm)}.fade{transition:opacity .15s linear}@media (prefers-reduced-motion:reduce){.fade{transition:none}}.fade:not(.show){opacity:0}.collapse:not(.show){display:none}.collapsing{height:0;overflow:hidden;transition:height .35s ease}@media (prefers-reduced-motion:reduce){.collapsing{transition:none}}.collapsing.collapse-horizontal{width:0;height:auto;transition:width .35s ease}@media (prefers-reduced-motion:reduce){.collapsing.collapse-horizontal{transition:none}}.dropdown,.dropdown-center,.dropend,.dropstart,.dropup,.dropup-center{position:relative}.dropdown-toggle{white-space:nowrap}.dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid;border-right:.3em solid transparent;border-bottom:0;border-left:.3em solid transparent}.dropdown-toggle:empty::after{margin-left:0}.dropdown-menu{--bs-dropdown-zindex:1000;--bs-dropdown-min-width:10rem;--bs-dropdown-padding-x:0;--bs-dropdown-padding-y:0.5rem;--bs-dropdown-spacer:0.125rem;--bs-dropdown-font-size:1rem;--bs-dropdown-color:var(--bs-body-color);--bs-dropdown-bg:var(--bs-body-bg);--bs-dropdown-border-color:var(--bs-border-color-translucent);--bs-dropdown-border-radius:var(--bs-border-radius);--bs-dropdown-border-width:var(--bs-border-width);--bs-dropdown-inner-border-radius:calc(var(--bs-border-radius) - var(--bs-border-width));--bs-dropdown-divider-bg:var(--bs-border-color-translucent);--bs-dropdown-divider-margin-y:0.5rem;--bs-dropdown-box-shadow:var(--bs-box-shadow);--bs-dropdown-link-color:var(--bs-body-color);--bs-dropdown-link-hover-color:#fff;--bs-dropdown-link-hover-bg:#2fa4e7;--bs-dropdown-link-active-color:#fff;--bs-dropdown-link-active-bg:#2fa4e7;--bs-dropdown-link-disabled-color:var(--bs-tertiary-color);--bs-dropdown-item-padding-x:1rem;--bs-dropdown-item-padding-y:0.25rem;--bs-dropdown-header-color:#868e96;--bs-dropdown-header-padding-x:1rem;--bs-dropdown-header-padding-y:0.5rem;position:absolute;z-index:var(--bs-dropdown-zindex);display:none;min-width:var(--bs-dropdown-min-width);padding:var(--bs-dropdown-padding-y) var(--bs-dropdown-padding-x);margin:0;font-size:var(--bs-dropdown-font-size);color:var(--bs-dropdown-color);text-align:left;list-style:none;background-color:var(--bs-dropdown-bg);background-clip:padding-box;border:var(--bs-dropdown-border-width) solid var(--bs-dropdown-border-color);border-radius:var(--bs-dropdown-border-radius)}.dropdown-menu[data-bs-popper]{top:100%;left:0;margin-top:var(--bs-dropdown-spacer)}.dropdown-menu-start{--bs-position:start}.dropdown-menu-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-end{--bs-position:end}.dropdown-menu-end[data-bs-popper]{right:0;left:auto}@media (min-width:576px){.dropdown-menu-sm-start{--bs-position:start}.dropdown-menu-sm-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-sm-end{--bs-position:end}.dropdown-menu-sm-end[data-bs-popper]{right:0;left:auto}}@media (min-width:768px){.dropdown-menu-md-start{--bs-position:start}.dropdown-menu-md-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-md-end{--bs-position:end}.dropdown-menu-md-end[data-bs-popper]{right:0;left:auto}}@media (min-width:992px){.dropdown-menu-lg-start{--bs-position:start}.dropdown-menu-lg-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-lg-end{--bs-position:end}.dropdown-menu-lg-end[data-bs-popper]{right:0;left:auto}}@media (min-width:1200px){.dropdown-menu-xl-start{--bs-position:start}.dropdown-menu-xl-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-xl-end{--bs-position:end}.dropdown-menu-xl-end[data-bs-popper]{right:0;left:auto}}@media (min-width:1400px){.dropdown-menu-xxl-start{--bs-position:start}.dropdown-menu-xxl-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-xxl-end{--bs-position:end}.dropdown-menu-xxl-end[data-bs-popper]{right:0;left:auto}}.dropup .dropdown-menu[data-bs-popper]{top:auto;bottom:100%;margin-top:0;margin-bottom:var(--bs-dropdown-spacer)}.dropup .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:0;border-right:.3em solid transparent;border-bottom:.3em solid;border-left:.3em solid transparent}.dropup .dropdown-toggle:empty::after{margin-left:0}.dropend .dropdown-menu[data-bs-popper]{top:0;right:auto;left:100%;margin-top:0;margin-left:var(--bs-dropdown-spacer)}.dropend .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:0;border-bottom:.3em solid transparent;border-left:.3em solid}.dropend .dropdown-toggle:empty::after{margin-left:0}.dropend .dropdown-toggle::after{vertical-align:0}.dropstart .dropdown-menu[data-bs-popper]{top:0;right:100%;left:auto;margin-top:0;margin-right:var(--bs-dropdown-spacer)}.dropstart .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:""}.dropstart .dropdown-toggle::after{display:none}.dropstart .dropdown-toggle::before{display:inline-block;margin-right:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:.3em solid;border-bottom:.3em solid transparent}.dropstart .dropdown-toggle:empty::after{margin-left:0}.dropstart .dropdown-toggle::before{vertical-align:0}.dropdown-divider{height:0;margin:var(--bs-dropdown-divider-margin-y) 0;overflow:hidden;border-top:1px solid var(--bs-dropdown-divider-bg);opacity:1}.dropdown-item{display:block;width:100%;padding:var(--bs-dropdown-item-padding-y) var(--bs-dropdown-item-padding-x);clear:both;font-weight:400;color:var(--bs-dropdown-link-color);text-align:inherit;text-decoration:none;white-space:nowrap;background-color:transparent;border:0;border-radius:var(--bs-dropdown-item-border-radius,0)}.dropdown-item:focus,.dropdown-item:hover{color:var(--bs-dropdown-link-hover-color);background-color:var(--bs-dropdown-link-hover-bg)}.dropdown-item.active,.dropdown-item:active{color:var(--bs-dropdown-link-active-color);text-decoration:none;background-color:var(--bs-dropdown-link-active-bg)}.dropdown-item.disabled,.dropdown-item:disabled{color:var(--bs-dropdown-link-disabled-color);pointer-events:none;background-color:transparent}.dropdown-menu.show{display:block}.dropdown-header{display:block;padding:var(--bs-dropdown-header-padding-y) var(--bs-dropdown-header-padding-x);margin-bottom:0;font-size:.875rem;color:var(--bs-dropdown-header-color);white-space:nowrap}.dropdown-item-text{display:block;padding:var(--bs-dropdown-item-padding-y) var(--bs-dropdown-item-padding-x);color:var(--bs-dropdown-link-color)}.dropdown-menu-dark{--bs-dropdown-color:#dee2e6;--bs-dropdown-bg:#343a40;--bs-dropdown-border-color:var(--bs-border-color-translucent);--bs-dropdown-box-shadow: ;--bs-dropdown-link-color:#dee2e6;--bs-dropdown-link-hover-color:#fff;--bs-dropdown-divider-bg:var(--bs-border-color-translucent);--bs-dropdown-link-hover-bg:rgba(255, 255, 255, 0.15);--bs-dropdown-link-active-color:#fff;--bs-dropdown-link-active-bg:#2fa4e7;--bs-dropdown-link-disabled-color:#adb5bd;--bs-dropdown-header-color:#adb5bd}.btn-group,.btn-group-vertical{position:relative;display:inline-flex;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;flex:1 1 auto}.btn-group-vertical>.btn-check:checked+.btn,.btn-group-vertical>.btn-check:focus+.btn,.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn-check:checked+.btn,.btn-group>.btn-check:focus+.btn,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:1}.btn-toolbar{display:flex;flex-wrap:wrap;justify-content:flex-start}.btn-toolbar .input-group{width:auto}.btn-group{border-radius:var(--bs-border-radius)}.btn-group>.btn-group:not(:first-child),.btn-group>:not(.btn-check:first-child)+.btn{margin-left:calc(var(--bs-border-width) * -1)}.btn-group>.btn-group:not(:last-child)>.btn,.btn-group>.btn.dropdown-toggle-split:first-child,.btn-group>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:not(:first-child)>.btn,.btn-group>.btn:nth-child(n+3),.btn-group>:not(.btn-check)+.btn{border-top-left-radius:0;border-bottom-left-radius:0}.dropdown-toggle-split{padding-right:.5625rem;padding-left:.5625rem}.dropdown-toggle-split::after,.dropend .dropdown-toggle-split::after,.dropup .dropdown-toggle-split::after{margin-left:0}.dropstart .dropdown-toggle-split::before{margin-right:0}.btn-group-sm>.btn+.dropdown-toggle-split,.btn-sm+.dropdown-toggle-split{padding-right:.375rem;padding-left:.375rem}.btn-group-lg>.btn+.dropdown-toggle-split,.btn-lg+.dropdown-toggle-split{padding-right:.75rem;padding-left:.75rem}.btn-group-vertical{flex-direction:column;align-items:flex-start;justify-content:center}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group{width:100%}.btn-group-vertical>.btn-group:not(:first-child),.btn-group-vertical>.btn:not(:first-child){margin-top:calc(var(--bs-border-width) * -1)}.btn-group-vertical>.btn-group:not(:last-child)>.btn,.btn-group-vertical>.btn:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child)>.btn,.btn-group-vertical>.btn~.btn{border-top-left-radius:0;border-top-right-radius:0}.nav{--bs-nav-link-padding-x:1rem;--bs-nav-link-padding-y:0.5rem;--bs-nav-link-font-weight: ;--bs-nav-link-color:var(--bs-link-color);--bs-nav-link-hover-color:var(--bs-link-hover-color);--bs-nav-link-disabled-color:var(--bs-secondary-color);display:flex;flex-wrap:wrap;padding-left:0;margin-bottom:0;list-style:none}.nav-link{display:block;padding:var(--bs-nav-link-padding-y) var(--bs-nav-link-padding-x);font-size:var(--bs-nav-link-font-size);font-weight:var(--bs-nav-link-font-weight);color:var(--bs-nav-link-color);text-decoration:none;background:0 0;border:0;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out}@media (prefers-reduced-motion:reduce){.nav-link{transition:none}}.nav-link:focus,.nav-link:hover{color:var(--bs-nav-link-hover-color)}.nav-link:focus-visible{outline:0;box-shadow:0 0 0 .25rem rgba(47,164,231,.25)}.nav-link.disabled,.nav-link:disabled{color:var(--bs-nav-link-disabled-color);pointer-events:none;cursor:default}.nav-tabs{--bs-nav-tabs-border-width:var(--bs-border-width);--bs-nav-tabs-border-color:var(--bs-border-color);--bs-nav-tabs-border-radius:var(--bs-border-radius);--bs-nav-tabs-link-hover-border-color:var(--bs-secondary-bg) var(--bs-secondary-bg) var(--bs-border-color);--bs-nav-tabs-link-active-color:var(--bs-emphasis-color);--bs-nav-tabs-link-active-bg:var(--bs-body-bg);--bs-nav-tabs-link-active-border-color:var(--bs-border-color) var(--bs-border-color) var(--bs-body-bg);border-bottom:var(--bs-nav-tabs-border-width) solid var(--bs-nav-tabs-border-color)}.nav-tabs .nav-link{margin-bottom:calc(-1 * var(--bs-nav-tabs-border-width));border:var(--bs-nav-tabs-border-width) solid transparent;border-top-left-radius:var(--bs-nav-tabs-border-radius);border-top-right-radius:var(--bs-nav-tabs-border-radius)}.nav-tabs .nav-link:focus,.nav-tabs .nav-link:hover{isolation:isolate;border-color:var(--bs-nav-tabs-link-hover-border-color)}.nav-tabs .nav-item.show .nav-link,.nav-tabs .nav-link.active{color:var(--bs-nav-tabs-link-active-color);background-color:var(--bs-nav-tabs-link-active-bg);border-color:var(--bs-nav-tabs-link-active-border-color)}.nav-tabs .dropdown-menu{margin-top:calc(-1 * var(--bs-nav-tabs-border-width));border-top-left-radius:0;border-top-right-radius:0}.nav-pills{--bs-nav-pills-border-radius:var(--bs-border-radius);--bs-nav-pills-link-active-color:#fff;--bs-nav-pills-link-active-bg:#2fa4e7}.nav-pills .nav-link{border-radius:var(--bs-nav-pills-border-radius)}.nav-pills .nav-link.active,.nav-pills .show>.nav-link{color:var(--bs-nav-pills-link-active-color);background-color:var(--bs-nav-pills-link-active-bg)}.nav-underline{--bs-nav-underline-gap:1rem;--bs-nav-underline-border-width:0.125rem;--bs-nav-underline-link-active-color:var(--bs-emphasis-color);gap:var(--bs-nav-underline-gap)}.nav-underline .nav-link{padding-right:0;padding-left:0;border-bottom:var(--bs-nav-underline-border-width) solid transparent}.nav-underline .nav-link:focus,.nav-underline .nav-link:hover{border-bottom-color:currentcolor}.nav-underline .nav-link.active,.nav-underline .show>.nav-link{font-weight:700;color:var(--bs-nav-underline-link-active-color);border-bottom-color:currentcolor}.nav-fill .nav-item,.nav-fill>.nav-link{flex:1 1 auto;text-align:center}.nav-justified .nav-item,.nav-justified>.nav-link{flex-basis:0;flex-grow:1;text-align:center}.nav-fill .nav-item .nav-link,.nav-justified .nav-item .nav-link{width:100%}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{--bs-navbar-padding-x:0;--bs-navbar-padding-y:0.5rem;--bs-navbar-color:rgba(var(--bs-emphasis-color-rgb), 0.65);--bs-navbar-hover-color:rgba(var(--bs-emphasis-color-rgb), 0.8);--bs-navbar-disabled-color:rgba(var(--bs-emphasis-color-rgb), 0.3);--bs-navbar-active-color:rgba(var(--bs-emphasis-color-rgb), 1);--bs-navbar-brand-padding-y:0.3125rem;--bs-navbar-brand-margin-end:1rem;--bs-navbar-brand-font-size:1.25rem;--bs-navbar-brand-color:rgba(var(--bs-emphasis-color-rgb), 1);--bs-navbar-brand-hover-color:rgba(var(--bs-emphasis-color-rgb), 1);--bs-navbar-nav-link-padding-x:0.5rem;--bs-navbar-toggler-padding-y:0.25rem;--bs-navbar-toggler-padding-x:0.75rem;--bs-navbar-toggler-font-size:1.25rem;--bs-navbar-toggler-icon-bg:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%2873, 80, 87, 0.75%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e");--bs-navbar-toggler-border-color:rgba(var(--bs-emphasis-color-rgb), 0.15);--bs-navbar-toggler-border-radius:var(--bs-border-radius);--bs-navbar-toggler-focus-width:0.25rem;--bs-navbar-toggler-transition:box-shadow 0.15s ease-in-out;position:relative;display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;padding:var(--bs-navbar-padding-y) var(--bs-navbar-padding-x)}.navbar>.container,.navbar>.container-fluid,.navbar>.container-lg,.navbar>.container-md,.navbar>.container-sm,.navbar>.container-xl,.navbar>.container-xxl{display:flex;flex-wrap:inherit;align-items:center;justify-content:space-between}.navbar-brand{padding-top:var(--bs-navbar-brand-padding-y);padding-bottom:var(--bs-navbar-brand-padding-y);margin-right:var(--bs-navbar-brand-margin-end);font-size:var(--bs-navbar-brand-font-size);color:var(--bs-navbar-brand-color);text-decoration:none;white-space:nowrap}.navbar-brand:focus,.navbar-brand:hover{color:var(--bs-navbar-brand-hover-color)}.navbar-nav{--bs-nav-link-padding-x:0;--bs-nav-link-padding-y:0.5rem;--bs-nav-link-font-weight: ;--bs-nav-link-color:var(--bs-navbar-color);--bs-nav-link-hover-color:var(--bs-navbar-hover-color);--bs-nav-link-disabled-color:var(--bs-navbar-disabled-color);display:flex;flex-direction:column;padding-left:0;margin-bottom:0;list-style:none}.navbar-nav .nav-link.active,.navbar-nav .nav-link.show{color:var(--bs-navbar-active-color)}.navbar-nav .dropdown-menu{position:static}.navbar-text{padding-top:.5rem;padding-bottom:.5rem;color:var(--bs-navbar-color)}.navbar-text a,.navbar-text a:focus,.navbar-text a:hover{color:var(--bs-navbar-active-color)}.navbar-collapse{flex-basis:100%;flex-grow:1;align-items:center}.navbar-toggler{padding:var(--bs-navbar-toggler-padding-y) var(--bs-navbar-toggler-padding-x);font-size:var(--bs-navbar-toggler-font-size);line-height:1;color:var(--bs-navbar-color);background-color:transparent;border:var(--bs-border-width) solid var(--bs-navbar-toggler-border-color);border-radius:var(--bs-navbar-toggler-border-radius);transition:var(--bs-navbar-toggler-transition)}@media (prefers-reduced-motion:reduce){.navbar-toggler{transition:none}}.navbar-toggler:hover{text-decoration:none}.navbar-toggler:focus{text-decoration:none;outline:0;box-shadow:0 0 0 var(--bs-navbar-toggler-focus-width)}.navbar-toggler-icon{display:inline-block;width:1.5em;height:1.5em;vertical-align:middle;background-image:var(--bs-navbar-toggler-icon-bg);background-repeat:no-repeat;background-position:center;background-size:100%}.navbar-nav-scroll{max-height:var(--bs-scroll-height,75vh);overflow-y:auto}@media (min-width:576px){.navbar-expand-sm{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-sm .navbar-nav{flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand-sm .navbar-nav-scroll{overflow:visible}.navbar-expand-sm .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-sm .navbar-toggler{display:none}.navbar-expand-sm .offcanvas{position:static;z-index:auto;flex-grow:1;width:auto!important;height:auto!important;visibility:visible!important;background-color:transparent!important;border:0!important;transform:none!important;transition:none}.navbar-expand-sm .offcanvas .offcanvas-header{display:none}.navbar-expand-sm .offcanvas .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}}@media (min-width:768px){.navbar-expand-md{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-md .navbar-nav{flex-direction:row}.navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-md .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand-md .navbar-nav-scroll{overflow:visible}.navbar-expand-md .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-md .navbar-toggler{display:none}.navbar-expand-md .offcanvas{position:static;z-index:auto;flex-grow:1;width:auto!important;height:auto!important;visibility:visible!important;background-color:transparent!important;border:0!important;transform:none!important;transition:none}.navbar-expand-md .offcanvas .offcanvas-header{display:none}.navbar-expand-md .offcanvas .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}}@media (min-width:992px){.navbar-expand-lg{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-lg .navbar-nav{flex-direction:row}.navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-lg .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand-lg .navbar-nav-scroll{overflow:visible}.navbar-expand-lg .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-lg .navbar-toggler{display:none}.navbar-expand-lg .offcanvas{position:static;z-index:auto;flex-grow:1;width:auto!important;height:auto!important;visibility:visible!important;background-color:transparent!important;border:0!important;transform:none!important;transition:none}.navbar-expand-lg .offcanvas .offcanvas-header{display:none}.navbar-expand-lg .offcanvas .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}}@media (min-width:1200px){.navbar-expand-xl{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-xl .navbar-nav{flex-direction:row}.navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xl .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand-xl .navbar-nav-scroll{overflow:visible}.navbar-expand-xl .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-xl .navbar-toggler{display:none}.navbar-expand-xl .offcanvas{position:static;z-index:auto;flex-grow:1;width:auto!important;height:auto!important;visibility:visible!important;background-color:transparent!important;border:0!important;transform:none!important;transition:none}.navbar-expand-xl .offcanvas .offcanvas-header{display:none}.navbar-expand-xl .offcanvas .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}}@media (min-width:1400px){.navbar-expand-xxl{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-xxl .navbar-nav{flex-direction:row}.navbar-expand-xxl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xxl .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand-xxl .navbar-nav-scroll{overflow:visible}.navbar-expand-xxl .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-xxl .navbar-toggler{display:none}.navbar-expand-xxl .offcanvas{position:static;z-index:auto;flex-grow:1;width:auto!important;height:auto!important;visibility:visible!important;background-color:transparent!important;border:0!important;transform:none!important;transition:none}.navbar-expand-xxl .offcanvas .offcanvas-header{display:none}.navbar-expand-xxl .offcanvas .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}}.navbar-expand{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand .navbar-nav{flex-direction:row}.navbar-expand .navbar-nav .dropdown-menu{position:absolute}.navbar-expand .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand .navbar-nav-scroll{overflow:visible}.navbar-expand .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand .navbar-toggler{display:none}.navbar-expand .offcanvas{position:static;z-index:auto;flex-grow:1;width:auto!important;height:auto!important;visibility:visible!important;background-color:transparent!important;border:0!important;transform:none!important;transition:none}.navbar-expand .offcanvas .offcanvas-header{display:none}.navbar-expand .offcanvas .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}.navbar-dark,.navbar[data-bs-theme=dark]{--bs-navbar-color:rgba(255, 255, 255, 0.8);--bs-navbar-hover-color:#fff;--bs-navbar-disabled-color:rgba(255, 255, 255, 0.25);--bs-navbar-active-color:#fff;--bs-navbar-brand-color:#fff;--bs-navbar-brand-hover-color:#fff;--bs-navbar-toggler-border-color:rgba(255, 255, 255, 0.1);--bs-navbar-toggler-icon-bg:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.8%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}[data-bs-theme=dark] .navbar-toggler-icon{--bs-navbar-toggler-icon-bg:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.8%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.card{--bs-card-spacer-y:1rem;--bs-card-spacer-x:1rem;--bs-card-title-spacer-y:0.5rem;--bs-card-title-color: ;--bs-card-subtitle-color: ;--bs-card-border-width:var(--bs-border-width);--bs-card-border-color:var(--bs-border-color-translucent);--bs-card-border-radius:var(--bs-border-radius);--bs-card-box-shadow: ;--bs-card-inner-border-radius:calc(var(--bs-border-radius) - (var(--bs-border-width)));--bs-card-cap-padding-y:0.5rem;--bs-card-cap-padding-x:1rem;--bs-card-cap-bg:rgba(var(--bs-body-color-rgb), 0.03);--bs-card-cap-color: ;--bs-card-height: ;--bs-card-color: ;--bs-card-bg:var(--bs-body-bg);--bs-card-img-overlay-padding:1rem;--bs-card-group-margin:0.75rem;position:relative;display:flex;flex-direction:column;min-width:0;height:var(--bs-card-height);color:var(--bs-body-color);word-wrap:break-word;background-color:var(--bs-card-bg);background-clip:border-box;border:var(--bs-card-border-width) solid var(--bs-card-border-color);border-radius:var(--bs-card-border-radius)}.card>hr{margin-right:0;margin-left:0}.card>.list-group{border-top:inherit;border-bottom:inherit}.card>.list-group:first-child{border-top-width:0;border-top-left-radius:var(--bs-card-inner-border-radius);border-top-right-radius:var(--bs-card-inner-border-radius)}.card>.list-group:last-child{border-bottom-width:0;border-bottom-right-radius:var(--bs-card-inner-border-radius);border-bottom-left-radius:var(--bs-card-inner-border-radius)}.card>.card-header+.list-group,.card>.list-group+.card-footer{border-top:0}.card-body{flex:1 1 auto;padding:var(--bs-card-spacer-y) var(--bs-card-spacer-x);color:var(--bs-card-color)}.card-title{margin-bottom:var(--bs-card-title-spacer-y);color:var(--bs-card-title-color)}.card-subtitle{margin-top:calc(-.5 * var(--bs-card-title-spacer-y));margin-bottom:0;color:var(--bs-card-subtitle-color)}.card-text:last-child{margin-bottom:0}.card-link+.card-link{margin-left:var(--bs-card-spacer-x)}.card-header{padding:var(--bs-card-cap-padding-y) var(--bs-card-cap-padding-x);margin-bottom:0;color:var(--bs-card-cap-color);background-color:var(--bs-card-cap-bg);border-bottom:var(--bs-card-border-width) solid var(--bs-card-border-color)}.card-header:first-child{border-radius:var(--bs-card-inner-border-radius) var(--bs-card-inner-border-radius) 0 0}.card-footer{padding:var(--bs-card-cap-padding-y) var(--bs-card-cap-padding-x);color:var(--bs-card-cap-color);background-color:var(--bs-card-cap-bg);border-top:var(--bs-card-border-width) solid var(--bs-card-border-color)}.card-footer:last-child{border-radius:0 0 var(--bs-card-inner-border-radius) var(--bs-card-inner-border-radius)}.card-header-tabs{margin-right:calc(-.5 * var(--bs-card-cap-padding-x));margin-bottom:calc(-1 * var(--bs-card-cap-padding-y));margin-left:calc(-.5 * var(--bs-card-cap-padding-x));border-bottom:0}.card-header-tabs .nav-link.active{background-color:var(--bs-card-bg);border-bottom-color:var(--bs-card-bg)}.card-header-pills{margin-right:calc(-.5 * var(--bs-card-cap-padding-x));margin-left:calc(-.5 * var(--bs-card-cap-padding-x))}.card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:var(--bs-card-img-overlay-padding);border-radius:var(--bs-card-inner-border-radius)}.card-img,.card-img-bottom,.card-img-top{width:100%}.card-img,.card-img-top{border-top-left-radius:var(--bs-card-inner-border-radius);border-top-right-radius:var(--bs-card-inner-border-radius)}.card-img,.card-img-bottom{border-bottom-right-radius:var(--bs-card-inner-border-radius);border-bottom-left-radius:var(--bs-card-inner-border-radius)}.card-group>.card{margin-bottom:var(--bs-card-group-margin)}@media (min-width:576px){.card-group{display:flex;flex-flow:row wrap}.card-group>.card{flex:1 0 0%;margin-bottom:0}.card-group>.card+.card{margin-left:0;border-left:0}.card-group>.card:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.card-group>.card:not(:last-child) .card-header,.card-group>.card:not(:last-child) .card-img-top{border-top-right-radius:0}.card-group>.card:not(:last-child) .card-footer,.card-group>.card:not(:last-child) .card-img-bottom{border-bottom-right-radius:0}.card-group>.card:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.card-group>.card:not(:first-child) .card-header,.card-group>.card:not(:first-child) .card-img-top{border-top-left-radius:0}.card-group>.card:not(:first-child) .card-footer,.card-group>.card:not(:first-child) .card-img-bottom{border-bottom-left-radius:0}}.accordion{--bs-accordion-color:var(--bs-body-color);--bs-accordion-bg:var(--bs-body-bg);--bs-accordion-transition:color 0.15s ease-in-out,background-color 0.15s ease-in-out,border-color 0.15s ease-in-out,box-shadow 0.15s ease-in-out,border-radius 0.15s ease;--bs-accordion-border-color:var(--bs-border-color);--bs-accordion-border-width:var(--bs-border-width);--bs-accordion-border-radius:var(--bs-border-radius);--bs-accordion-inner-border-radius:calc(var(--bs-border-radius) - (var(--bs-border-width)));--bs-accordion-btn-padding-x:1.25rem;--bs-accordion-btn-padding-y:1rem;--bs-accordion-btn-color:var(--bs-body-color);--bs-accordion-btn-bg:var(--bs-accordion-bg);--bs-accordion-btn-icon:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23495057'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");--bs-accordion-btn-icon-width:1.25rem;--bs-accordion-btn-icon-transform:rotate(-180deg);--bs-accordion-btn-icon-transition:transform 0.2s ease-in-out;--bs-accordion-btn-active-icon:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%2313425c'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");--bs-accordion-btn-focus-border-color:#97d2f3;--bs-accordion-btn-focus-box-shadow:0 0 0 0.25rem rgba(47, 164, 231, 0.25);--bs-accordion-body-padding-x:1.25rem;--bs-accordion-body-padding-y:1rem;--bs-accordion-active-color:var(--bs-primary-text-emphasis);--bs-accordion-active-bg:var(--bs-primary-bg-subtle)}.accordion-button{position:relative;display:flex;align-items:center;width:100%;padding:var(--bs-accordion-btn-padding-y) var(--bs-accordion-btn-padding-x);font-size:1rem;color:var(--bs-accordion-btn-color);text-align:left;background-color:var(--bs-accordion-btn-bg);border:0;border-radius:0;overflow-anchor:none;transition:var(--bs-accordion-transition)}@media (prefers-reduced-motion:reduce){.accordion-button{transition:none}}.accordion-button:not(.collapsed){color:var(--bs-accordion-active-color);background-color:var(--bs-accordion-active-bg);box-shadow:inset 0 calc(-1 * var(--bs-accordion-border-width)) 0 var(--bs-accordion-border-color)}.accordion-button:not(.collapsed)::after{background-image:var(--bs-accordion-btn-active-icon);transform:var(--bs-accordion-btn-icon-transform)}.accordion-button::after{flex-shrink:0;width:var(--bs-accordion-btn-icon-width);height:var(--bs-accordion-btn-icon-width);margin-left:auto;content:"";background-image:var(--bs-accordion-btn-icon);background-repeat:no-repeat;background-size:var(--bs-accordion-btn-icon-width);transition:var(--bs-accordion-btn-icon-transition)}@media (prefers-reduced-motion:reduce){.accordion-button::after{transition:none}}.accordion-button:hover{z-index:2}.accordion-button:focus{z-index:3;border-color:var(--bs-accordion-btn-focus-border-color);outline:0;box-shadow:var(--bs-accordion-btn-focus-box-shadow)}.accordion-header{margin-bottom:0}.accordion-item{color:var(--bs-accordion-color);background-color:var(--bs-accordion-bg);border:var(--bs-accordion-border-width) solid var(--bs-accordion-border-color)}.accordion-item:first-of-type{border-top-left-radius:var(--bs-accordion-border-radius);border-top-right-radius:var(--bs-accordion-border-radius)}.accordion-item:first-of-type .accordion-button{border-top-left-radius:var(--bs-accordion-inner-border-radius);border-top-right-radius:var(--bs-accordion-inner-border-radius)}.accordion-item:not(:first-of-type){border-top:0}.accordion-item:last-of-type{border-bottom-right-radius:var(--bs-accordion-border-radius);border-bottom-left-radius:var(--bs-accordion-border-radius)}.accordion-item:last-of-type .accordion-button.collapsed{border-bottom-right-radius:var(--bs-accordion-inner-border-radius);border-bottom-left-radius:var(--bs-accordion-inner-border-radius)}.accordion-item:last-of-type .accordion-collapse{border-bottom-right-radius:var(--bs-accordion-border-radius);border-bottom-left-radius:var(--bs-accordion-border-radius)}.accordion-body{padding:var(--bs-accordion-body-padding-y) var(--bs-accordion-body-padding-x)}.accordion-flush .accordion-collapse{border-width:0}.accordion-flush .accordion-item{border-right:0;border-left:0;border-radius:0}.accordion-flush .accordion-item:first-child{border-top:0}.accordion-flush .accordion-item:last-child{border-bottom:0}.accordion-flush .accordion-item .accordion-button,.accordion-flush .accordion-item .accordion-button.collapsed{border-radius:0}[data-bs-theme=dark] .accordion-button::after{--bs-accordion-btn-icon:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%2382c8f1'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");--bs-accordion-btn-active-icon:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%2382c8f1'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e")}.breadcrumb{--bs-breadcrumb-padding-x:0;--bs-breadcrumb-padding-y:0;--bs-breadcrumb-margin-bottom:1rem;--bs-breadcrumb-bg: ;--bs-breadcrumb-border-radius: ;--bs-breadcrumb-divider-color:var(--bs-secondary-color);--bs-breadcrumb-item-padding-x:0.5rem;--bs-breadcrumb-item-active-color:var(--bs-secondary-color);display:flex;flex-wrap:wrap;padding:var(--bs-breadcrumb-padding-y) var(--bs-breadcrumb-padding-x);margin-bottom:var(--bs-breadcrumb-margin-bottom);font-size:var(--bs-breadcrumb-font-size);list-style:none;background-color:var(--bs-breadcrumb-bg);border-radius:var(--bs-breadcrumb-border-radius)}.breadcrumb-item+.breadcrumb-item{padding-left:var(--bs-breadcrumb-item-padding-x)}.breadcrumb-item+.breadcrumb-item::before{float:left;padding-right:var(--bs-breadcrumb-item-padding-x);color:var(--bs-breadcrumb-divider-color);content:var(--bs-breadcrumb-divider, "/")}.breadcrumb-item.active{color:var(--bs-breadcrumb-item-active-color)}.pagination{--bs-pagination-padding-x:0.75rem;--bs-pagination-padding-y:0.375rem;--bs-pagination-font-size:1rem;--bs-pagination-color:var(--bs-link-color);--bs-pagination-bg:var(--bs-body-bg);--bs-pagination-border-width:var(--bs-border-width);--bs-pagination-border-color:var(--bs-border-color);--bs-pagination-border-radius:var(--bs-border-radius);--bs-pagination-hover-color:var(--bs-link-hover-color);--bs-pagination-hover-bg:var(--bs-tertiary-bg);--bs-pagination-hover-border-color:var(--bs-border-color);--bs-pagination-focus-color:var(--bs-link-hover-color);--bs-pagination-focus-bg:var(--bs-secondary-bg);--bs-pagination-focus-box-shadow:0 0 0 0.25rem rgba(47, 164, 231, 0.25);--bs-pagination-active-color:#fff;--bs-pagination-active-bg:#2fa4e7;--bs-pagination-active-border-color:#2fa4e7;--bs-pagination-disabled-color:var(--bs-secondary-color);--bs-pagination-disabled-bg:var(--bs-secondary-bg);--bs-pagination-disabled-border-color:var(--bs-border-color);display:flex;padding-left:0;list-style:none}.page-link{position:relative;display:block;padding:var(--bs-pagination-padding-y) var(--bs-pagination-padding-x);font-size:var(--bs-pagination-font-size);color:var(--bs-pagination-color);text-decoration:none;background-color:var(--bs-pagination-bg);border:var(--bs-pagination-border-width) solid var(--bs-pagination-border-color);transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.page-link{transition:none}}.page-link:hover{z-index:2;color:var(--bs-pagination-hover-color);background-color:var(--bs-pagination-hover-bg);border-color:var(--bs-pagination-hover-border-color)}.page-link:focus{z-index:3;color:var(--bs-pagination-focus-color);background-color:var(--bs-pagination-focus-bg);outline:0;box-shadow:var(--bs-pagination-focus-box-shadow)}.active>.page-link,.page-link.active{z-index:3;color:var(--bs-pagination-active-color);background-color:var(--bs-pagination-active-bg);border-color:var(--bs-pagination-active-border-color)}.disabled>.page-link,.page-link.disabled{color:var(--bs-pagination-disabled-color);pointer-events:none;background-color:var(--bs-pagination-disabled-bg);border-color:var(--bs-pagination-disabled-border-color)}.page-item:not(:first-child) .page-link{margin-left:calc(var(--bs-border-width) * -1)}.page-item:first-child .page-link{border-top-left-radius:var(--bs-pagination-border-radius);border-bottom-left-radius:var(--bs-pagination-border-radius)}.page-item:last-child .page-link{border-top-right-radius:var(--bs-pagination-border-radius);border-bottom-right-radius:var(--bs-pagination-border-radius)}.pagination-lg{--bs-pagination-padding-x:1.5rem;--bs-pagination-padding-y:0.75rem;--bs-pagination-font-size:1.25rem;--bs-pagination-border-radius:var(--bs-border-radius-lg)}.pagination-sm{--bs-pagination-padding-x:0.5rem;--bs-pagination-padding-y:0.25rem;--bs-pagination-font-size:0.875rem;--bs-pagination-border-radius:var(--bs-border-radius-sm)}.badge{--bs-badge-padding-x:0.65em;--bs-badge-padding-y:0.35em;--bs-badge-font-size:0.75em;--bs-badge-font-weight:700;--bs-badge-color:#fff;--bs-badge-border-radius:var(--bs-border-radius);display:inline-block;padding:var(--bs-badge-padding-y) var(--bs-badge-padding-x);font-size:var(--bs-badge-font-size);font-weight:var(--bs-badge-font-weight);line-height:1;color:var(--bs-badge-color);text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:var(--bs-badge-border-radius)}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.alert{--bs-alert-bg:transparent;--bs-alert-padding-x:1rem;--bs-alert-padding-y:1rem;--bs-alert-margin-bottom:1rem;--bs-alert-color:inherit;--bs-alert-border-color:transparent;--bs-alert-border:var(--bs-border-width) solid var(--bs-alert-border-color);--bs-alert-border-radius:var(--bs-border-radius);--bs-alert-link-color:inherit;position:relative;padding:var(--bs-alert-padding-y) var(--bs-alert-padding-x);margin-bottom:var(--bs-alert-margin-bottom);color:var(--bs-alert-color);background-color:var(--bs-alert-bg);border:var(--bs-alert-border);border-radius:var(--bs-alert-border-radius)}.alert-heading{color:inherit}.alert-link{font-weight:700;color:var(--bs-alert-link-color)}.alert-dismissible{padding-right:3rem}.alert-dismissible .btn-close{position:absolute;top:0;right:0;z-index:2;padding:1.25rem 1rem}.alert-primary{--bs-alert-color:var(--bs-primary-text-emphasis);--bs-alert-bg:var(--bs-primary-bg-subtle);--bs-alert-border-color:var(--bs-primary-border-subtle);--bs-alert-link-color:var(--bs-primary-text-emphasis)}.alert-secondary{--bs-alert-color:var(--bs-secondary-text-emphasis);--bs-alert-bg:var(--bs-secondary-bg-subtle);--bs-alert-border-color:var(--bs-secondary-border-subtle);--bs-alert-link-color:var(--bs-secondary-text-emphasis)}.alert-success{--bs-alert-color:var(--bs-success-text-emphasis);--bs-alert-bg:var(--bs-success-bg-subtle);--bs-alert-border-color:var(--bs-success-border-subtle);--bs-alert-link-color:var(--bs-success-text-emphasis)}.alert-info{--bs-alert-color:var(--bs-info-text-emphasis);--bs-alert-bg:var(--bs-info-bg-subtle);--bs-alert-border-color:var(--bs-info-border-subtle);--bs-alert-link-color:var(--bs-info-text-emphasis)}.alert-warning{--bs-alert-color:var(--bs-warning-text-emphasis);--bs-alert-bg:var(--bs-warning-bg-subtle);--bs-alert-border-color:var(--bs-warning-border-subtle);--bs-alert-link-color:var(--bs-warning-text-emphasis)}.alert-danger{--bs-alert-color:var(--bs-danger-text-emphasis);--bs-alert-bg:var(--bs-danger-bg-subtle);--bs-alert-border-color:var(--bs-danger-border-subtle);--bs-alert-link-color:var(--bs-danger-text-emphasis)}.alert-light{--bs-alert-color:var(--bs-light-text-emphasis);--bs-alert-bg:var(--bs-light-bg-subtle);--bs-alert-border-color:var(--bs-light-border-subtle);--bs-alert-link-color:var(--bs-light-text-emphasis)}.alert-dark{--bs-alert-color:var(--bs-dark-text-emphasis);--bs-alert-bg:var(--bs-dark-bg-subtle);--bs-alert-border-color:var(--bs-dark-border-subtle);--bs-alert-link-color:var(--bs-dark-text-emphasis)}@keyframes progress-bar-stripes{0%{background-position-x:1rem}}.progress,.progress-stacked{--bs-progress-height:1rem;--bs-progress-font-size:0.75rem;--bs-progress-bg:var(--bs-secondary-bg);--bs-progress-border-radius:var(--bs-border-radius);--bs-progress-box-shadow:var(--bs-box-shadow-inset);--bs-progress-bar-color:#fff;--bs-progress-bar-bg:#2fa4e7;--bs-progress-bar-transition:width 0.6s ease;display:flex;height:var(--bs-progress-height);overflow:hidden;font-size:var(--bs-progress-font-size);background-color:var(--bs-progress-bg);border-radius:var(--bs-progress-border-radius)}.progress-bar{display:flex;flex-direction:column;justify-content:center;overflow:hidden;color:var(--bs-progress-bar-color);text-align:center;white-space:nowrap;background-color:var(--bs-progress-bar-bg);transition:var(--bs-progress-bar-transition)}@media (prefers-reduced-motion:reduce){.progress-bar{transition:none}}.progress-bar-striped{background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-size:var(--bs-progress-height) var(--bs-progress-height)}.progress-stacked>.progress{overflow:visible}.progress-stacked>.progress>.progress-bar{width:100%}.progress-bar-animated{animation:1s linear infinite progress-bar-stripes}@media (prefers-reduced-motion:reduce){.progress-bar-animated{animation:none}}.list-group{--bs-list-group-color:var(--bs-body-color);--bs-list-group-bg:var(--bs-body-bg);--bs-list-group-border-color:var(--bs-border-color);--bs-list-group-border-width:var(--bs-border-width);--bs-list-group-border-radius:var(--bs-border-radius);--bs-list-group-item-padding-x:1rem;--bs-list-group-item-padding-y:0.5rem;--bs-list-group-action-color:var(--bs-secondary-color);--bs-list-group-action-hover-color:var(--bs-emphasis-color);--bs-list-group-action-hover-bg:var(--bs-tertiary-bg);--bs-list-group-action-active-color:var(--bs-body-color);--bs-list-group-action-active-bg:var(--bs-secondary-bg);--bs-list-group-disabled-color:var(--bs-secondary-color);--bs-list-group-disabled-bg:var(--bs-body-bg);--bs-list-group-active-color:#fff;--bs-list-group-active-bg:#2fa4e7;--bs-list-group-active-border-color:#2fa4e7;display:flex;flex-direction:column;padding-left:0;margin-bottom:0;border-radius:var(--bs-list-group-border-radius)}.list-group-numbered{list-style-type:none;counter-reset:section}.list-group-numbered>.list-group-item::before{content:counters(section, ".") ". ";counter-increment:section}.list-group-item-action{width:100%;color:var(--bs-list-group-action-color);text-align:inherit}.list-group-item-action:focus,.list-group-item-action:hover{z-index:1;color:var(--bs-list-group-action-hover-color);text-decoration:none;background-color:var(--bs-list-group-action-hover-bg)}.list-group-item-action:active{color:var(--bs-list-group-action-active-color);background-color:var(--bs-list-group-action-active-bg)}.list-group-item{position:relative;display:block;padding:var(--bs-list-group-item-padding-y) var(--bs-list-group-item-padding-x);color:var(--bs-list-group-color);text-decoration:none;background-color:var(--bs-list-group-bg);border:var(--bs-list-group-border-width) solid var(--bs-list-group-border-color)}.list-group-item:first-child{border-top-left-radius:inherit;border-top-right-radius:inherit}.list-group-item:last-child{border-bottom-right-radius:inherit;border-bottom-left-radius:inherit}.list-group-item.disabled,.list-group-item:disabled{color:var(--bs-list-group-disabled-color);pointer-events:none;background-color:var(--bs-list-group-disabled-bg)}.list-group-item.active{z-index:2;color:var(--bs-list-group-active-color);background-color:var(--bs-list-group-active-bg);border-color:var(--bs-list-group-active-border-color)}.list-group-item+.list-group-item{border-top-width:0}.list-group-item+.list-group-item.active{margin-top:calc(-1 * var(--bs-list-group-border-width));border-top-width:var(--bs-list-group-border-width)}.list-group-horizontal{flex-direction:row}.list-group-horizontal>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal>.list-group-item.active{margin-top:0}.list-group-horizontal>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal>.list-group-item+.list-group-item.active{margin-left:calc(-1 * var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}@media (min-width:576px){.list-group-horizontal-sm{flex-direction:row}.list-group-horizontal-sm>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-sm>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-sm>.list-group-item.active{margin-top:0}.list-group-horizontal-sm>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal-sm>.list-group-item+.list-group-item.active{margin-left:calc(-1 * var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}}@media (min-width:768px){.list-group-horizontal-md{flex-direction:row}.list-group-horizontal-md>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-md>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-md>.list-group-item.active{margin-top:0}.list-group-horizontal-md>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal-md>.list-group-item+.list-group-item.active{margin-left:calc(-1 * var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}}@media (min-width:992px){.list-group-horizontal-lg{flex-direction:row}.list-group-horizontal-lg>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-lg>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-lg>.list-group-item.active{margin-top:0}.list-group-horizontal-lg>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal-lg>.list-group-item+.list-group-item.active{margin-left:calc(-1 * var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}}@media (min-width:1200px){.list-group-horizontal-xl{flex-direction:row}.list-group-horizontal-xl>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-xl>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-xl>.list-group-item.active{margin-top:0}.list-group-horizontal-xl>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal-xl>.list-group-item+.list-group-item.active{margin-left:calc(-1 * var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}}@media (min-width:1400px){.list-group-horizontal-xxl{flex-direction:row}.list-group-horizontal-xxl>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-xxl>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-xxl>.list-group-item.active{margin-top:0}.list-group-horizontal-xxl>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal-xxl>.list-group-item+.list-group-item.active{margin-left:calc(-1 * var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}}.list-group-flush{border-radius:0}.list-group-flush>.list-group-item{border-width:0 0 var(--bs-list-group-border-width)}.list-group-flush>.list-group-item:last-child{border-bottom-width:0}.list-group-item-primary{--bs-list-group-color:var(--bs-primary-text-emphasis);--bs-list-group-bg:var(--bs-primary-bg-subtle);--bs-list-group-border-color:var(--bs-primary-border-subtle);--bs-list-group-action-hover-color:var(--bs-emphasis-color);--bs-list-group-action-hover-bg:var(--bs-primary-border-subtle);--bs-list-group-action-active-color:var(--bs-emphasis-color);--bs-list-group-action-active-bg:var(--bs-primary-border-subtle);--bs-list-group-active-color:var(--bs-primary-bg-subtle);--bs-list-group-active-bg:var(--bs-primary-text-emphasis);--bs-list-group-active-border-color:var(--bs-primary-text-emphasis)}.list-group-item-secondary{--bs-list-group-color:var(--bs-secondary-text-emphasis);--bs-list-group-bg:var(--bs-secondary-bg-subtle);--bs-list-group-border-color:var(--bs-secondary-border-subtle);--bs-list-group-action-hover-color:var(--bs-emphasis-color);--bs-list-group-action-hover-bg:var(--bs-secondary-border-subtle);--bs-list-group-action-active-color:var(--bs-emphasis-color);--bs-list-group-action-active-bg:var(--bs-secondary-border-subtle);--bs-list-group-active-color:var(--bs-secondary-bg-subtle);--bs-list-group-active-bg:var(--bs-secondary-text-emphasis);--bs-list-group-active-border-color:var(--bs-secondary-text-emphasis)}.list-group-item-success{--bs-list-group-color:var(--bs-success-text-emphasis);--bs-list-group-bg:var(--bs-success-bg-subtle);--bs-list-group-border-color:var(--bs-success-border-subtle);--bs-list-group-action-hover-color:var(--bs-emphasis-color);--bs-list-group-action-hover-bg:var(--bs-success-border-subtle);--bs-list-group-action-active-color:var(--bs-emphasis-color);--bs-list-group-action-active-bg:var(--bs-success-border-subtle);--bs-list-group-active-color:var(--bs-success-bg-subtle);--bs-list-group-active-bg:var(--bs-success-text-emphasis);--bs-list-group-active-border-color:var(--bs-success-text-emphasis)}.list-group-item-info{--bs-list-group-color:var(--bs-info-text-emphasis);--bs-list-group-bg:var(--bs-info-bg-subtle);--bs-list-group-border-color:var(--bs-info-border-subtle);--bs-list-group-action-hover-color:var(--bs-emphasis-color);--bs-list-group-action-hover-bg:var(--bs-info-border-subtle);--bs-list-group-action-active-color:var(--bs-emphasis-color);--bs-list-group-action-active-bg:var(--bs-info-border-subtle);--bs-list-group-active-color:var(--bs-info-bg-subtle);--bs-list-group-active-bg:var(--bs-info-text-emphasis);--bs-list-group-active-border-color:var(--bs-info-text-emphasis)}.list-group-item-warning{--bs-list-group-color:var(--bs-warning-text-emphasis);--bs-list-group-bg:var(--bs-warning-bg-subtle);--bs-list-group-border-color:var(--bs-warning-border-subtle);--bs-list-group-action-hover-color:var(--bs-emphasis-color);--bs-list-group-action-hover-bg:var(--bs-warning-border-subtle);--bs-list-group-action-active-color:var(--bs-emphasis-color);--bs-list-group-action-active-bg:var(--bs-warning-border-subtle);--bs-list-group-active-color:var(--bs-warning-bg-subtle);--bs-list-group-active-bg:var(--bs-warning-text-emphasis);--bs-list-group-active-border-color:var(--bs-warning-text-emphasis)}.list-group-item-danger{--bs-list-group-color:var(--bs-danger-text-emphasis);--bs-list-group-bg:var(--bs-danger-bg-subtle);--bs-list-group-border-color:var(--bs-danger-border-subtle);--bs-list-group-action-hover-color:var(--bs-emphasis-color);--bs-list-group-action-hover-bg:var(--bs-danger-border-subtle);--bs-list-group-action-active-color:var(--bs-emphasis-color);--bs-list-group-action-active-bg:var(--bs-danger-border-subtle);--bs-list-group-active-color:var(--bs-danger-bg-subtle);--bs-list-group-active-bg:var(--bs-danger-text-emphasis);--bs-list-group-active-border-color:var(--bs-danger-text-emphasis)}.list-group-item-light{--bs-list-group-color:var(--bs-light-text-emphasis);--bs-list-group-bg:var(--bs-light-bg-subtle);--bs-list-group-border-color:var(--bs-light-border-subtle);--bs-list-group-action-hover-color:var(--bs-emphasis-color);--bs-list-group-action-hover-bg:var(--bs-light-border-subtle);--bs-list-group-action-active-color:var(--bs-emphasis-color);--bs-list-group-action-active-bg:var(--bs-light-border-subtle);--bs-list-group-active-color:var(--bs-light-bg-subtle);--bs-list-group-active-bg:var(--bs-light-text-emphasis);--bs-list-group-active-border-color:var(--bs-light-text-emphasis)}.list-group-item-dark{--bs-list-group-color:var(--bs-dark-text-emphasis);--bs-list-group-bg:var(--bs-dark-bg-subtle);--bs-list-group-border-color:var(--bs-dark-border-subtle);--bs-list-group-action-hover-color:var(--bs-emphasis-color);--bs-list-group-action-hover-bg:var(--bs-dark-border-subtle);--bs-list-group-action-active-color:var(--bs-emphasis-color);--bs-list-group-action-active-bg:var(--bs-dark-border-subtle);--bs-list-group-active-color:var(--bs-dark-bg-subtle);--bs-list-group-active-bg:var(--bs-dark-text-emphasis);--bs-list-group-active-border-color:var(--bs-dark-text-emphasis)}.btn-close{--bs-btn-close-color:#000;--bs-btn-close-bg:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23000'%3e%3cpath d='M.293.293a1 1 0 0 1 1.414 0L8 6.586 14.293.293a1 1 0 1 1 1.414 1.414L9.414 8l6.293 6.293a1 1 0 0 1-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 0 1-1.414-1.414L6.586 8 .293 1.707a1 1 0 0 1 0-1.414z'/%3e%3c/svg%3e");--bs-btn-close-opacity:0.5;--bs-btn-close-hover-opacity:0.75;--bs-btn-close-focus-shadow:0 0 0 0.25rem rgba(47, 164, 231, 0.25);--bs-btn-close-focus-opacity:1;--bs-btn-close-disabled-opacity:0.25;--bs-btn-close-white-filter:invert(1) grayscale(100%) brightness(200%);box-sizing:content-box;width:1em;height:1em;padding:.25em .25em;color:var(--bs-btn-close-color);background:transparent var(--bs-btn-close-bg) center/1em auto no-repeat;border:0;border-radius:.375rem;opacity:var(--bs-btn-close-opacity)}.btn-close:hover{color:var(--bs-btn-close-color);text-decoration:none;opacity:var(--bs-btn-close-hover-opacity)}.btn-close:focus{outline:0;box-shadow:var(--bs-btn-close-focus-shadow);opacity:var(--bs-btn-close-focus-opacity)}.btn-close.disabled,.btn-close:disabled{pointer-events:none;-webkit-user-select:none;-moz-user-select:none;user-select:none;opacity:var(--bs-btn-close-disabled-opacity)}.btn-close-white{filter:var(--bs-btn-close-white-filter)}[data-bs-theme=dark] .btn-close{filter:var(--bs-btn-close-white-filter)}.toast{--bs-toast-zindex:1090;--bs-toast-padding-x:0.75rem;--bs-toast-padding-y:0.5rem;--bs-toast-spacing:1.5rem;--bs-toast-max-width:350px;--bs-toast-font-size:0.875rem;--bs-toast-color: ;--bs-toast-bg:rgba(var(--bs-body-bg-rgb), 0.85);--bs-toast-border-width:var(--bs-border-width);--bs-toast-border-color:var(--bs-border-color-translucent);--bs-toast-border-radius:var(--bs-border-radius);--bs-toast-box-shadow:var(--bs-box-shadow);--bs-toast-header-color:var(--bs-secondary-color);--bs-toast-header-bg:rgba(var(--bs-body-bg-rgb), 0.85);--bs-toast-header-border-color:var(--bs-border-color-translucent);width:var(--bs-toast-max-width);max-width:100%;font-size:var(--bs-toast-font-size);color:var(--bs-toast-color);pointer-events:auto;background-color:var(--bs-toast-bg);background-clip:padding-box;border:var(--bs-toast-border-width) solid var(--bs-toast-border-color);box-shadow:var(--bs-toast-box-shadow);border-radius:var(--bs-toast-border-radius)}.toast.showing{opacity:0}.toast:not(.show){display:none}.toast-container{--bs-toast-zindex:1090;position:absolute;z-index:var(--bs-toast-zindex);width:-webkit-max-content;width:-moz-max-content;width:max-content;max-width:100%;pointer-events:none}.toast-container>:not(:last-child){margin-bottom:var(--bs-toast-spacing)}.toast-header{display:flex;align-items:center;padding:var(--bs-toast-padding-y) var(--bs-toast-padding-x);color:var(--bs-toast-header-color);background-color:var(--bs-toast-header-bg);background-clip:padding-box;border-bottom:var(--bs-toast-border-width) solid var(--bs-toast-header-border-color);border-top-left-radius:calc(var(--bs-toast-border-radius) - var(--bs-toast-border-width));border-top-right-radius:calc(var(--bs-toast-border-radius) - var(--bs-toast-border-width))}.toast-header .btn-close{margin-right:calc(-.5 * var(--bs-toast-padding-x));margin-left:var(--bs-toast-padding-x)}.toast-body{padding:var(--bs-toast-padding-x);word-wrap:break-word}.modal{--bs-modal-zindex:1055;--bs-modal-width:500px;--bs-modal-padding:1rem;--bs-modal-margin:0.5rem;--bs-modal-color: ;--bs-modal-bg:var(--bs-body-bg);--bs-modal-border-color:var(--bs-border-color-translucent);--bs-modal-border-width:var(--bs-border-width);--bs-modal-border-radius:var(--bs-border-radius-lg);--bs-modal-box-shadow:var(--bs-box-shadow-sm);--bs-modal-inner-border-radius:calc(var(--bs-border-radius-lg) - (var(--bs-border-width)));--bs-modal-header-padding-x:1rem;--bs-modal-header-padding-y:1rem;--bs-modal-header-padding:1rem 1rem;--bs-modal-header-border-color:var(--bs-border-color);--bs-modal-header-border-width:var(--bs-border-width);--bs-modal-title-line-height:1.5;--bs-modal-footer-gap:0.5rem;--bs-modal-footer-bg: ;--bs-modal-footer-border-color:var(--bs-border-color);--bs-modal-footer-border-width:var(--bs-border-width);position:fixed;top:0;left:0;z-index:var(--bs-modal-zindex);display:none;width:100%;height:100%;overflow-x:hidden;overflow-y:auto;outline:0}.modal-dialog{position:relative;width:auto;margin:var(--bs-modal-margin);pointer-events:none}.modal.fade .modal-dialog{transition:transform .3s ease-out;transform:translate(0,-50px)}@media (prefers-reduced-motion:reduce){.modal.fade .modal-dialog{transition:none}}.modal.show .modal-dialog{transform:none}.modal.modal-static .modal-dialog{transform:scale(1.02)}.modal-dialog-scrollable{height:calc(100% - var(--bs-modal-margin) * 2)}.modal-dialog-scrollable .modal-content{max-height:100%;overflow:hidden}.modal-dialog-scrollable .modal-body{overflow-y:auto}.modal-dialog-centered{display:flex;align-items:center;min-height:calc(100% - var(--bs-modal-margin) * 2)}.modal-content{position:relative;display:flex;flex-direction:column;width:100%;color:var(--bs-modal-color);pointer-events:auto;background-color:var(--bs-modal-bg);background-clip:padding-box;border:var(--bs-modal-border-width) solid var(--bs-modal-border-color);border-radius:var(--bs-modal-border-radius);outline:0}.modal-backdrop{--bs-backdrop-zindex:1050;--bs-backdrop-bg:#000;--bs-backdrop-opacity:0.5;position:fixed;top:0;left:0;z-index:var(--bs-backdrop-zindex);width:100vw;height:100vh;background-color:var(--bs-backdrop-bg)}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:var(--bs-backdrop-opacity)}.modal-header{display:flex;flex-shrink:0;align-items:center;justify-content:space-between;padding:var(--bs-modal-header-padding);border-bottom:var(--bs-modal-header-border-width) solid var(--bs-modal-header-border-color);border-top-left-radius:var(--bs-modal-inner-border-radius);border-top-right-radius:var(--bs-modal-inner-border-radius)}.modal-header .btn-close{padding:calc(var(--bs-modal-header-padding-y) * .5) calc(var(--bs-modal-header-padding-x) * .5);margin:calc(-.5 * var(--bs-modal-header-padding-y)) calc(-.5 * var(--bs-modal-header-padding-x)) calc(-.5 * var(--bs-modal-header-padding-y)) auto}.modal-title{margin-bottom:0;line-height:var(--bs-modal-title-line-height)}.modal-body{position:relative;flex:1 1 auto;padding:var(--bs-modal-padding)}.modal-footer{display:flex;flex-shrink:0;flex-wrap:wrap;align-items:center;justify-content:flex-end;padding:calc(var(--bs-modal-padding) - var(--bs-modal-footer-gap) * .5);background-color:var(--bs-modal-footer-bg);border-top:var(--bs-modal-footer-border-width) solid var(--bs-modal-footer-border-color);border-bottom-right-radius:var(--bs-modal-inner-border-radius);border-bottom-left-radius:var(--bs-modal-inner-border-radius)}.modal-footer>*{margin:calc(var(--bs-modal-footer-gap) * .5)}@media (min-width:576px){.modal{--bs-modal-margin:1.75rem;--bs-modal-box-shadow:var(--bs-box-shadow)}.modal-dialog{max-width:var(--bs-modal-width);margin-right:auto;margin-left:auto}.modal-sm{--bs-modal-width:300px}}@media (min-width:992px){.modal-lg,.modal-xl{--bs-modal-width:800px}}@media (min-width:1200px){.modal-xl{--bs-modal-width:1140px}}.modal-fullscreen{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen .modal-footer,.modal-fullscreen .modal-header{border-radius:0}.modal-fullscreen .modal-body{overflow-y:auto}@media (max-width:575.98px){.modal-fullscreen-sm-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-sm-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-sm-down .modal-footer,.modal-fullscreen-sm-down .modal-header{border-radius:0}.modal-fullscreen-sm-down .modal-body{overflow-y:auto}}@media (max-width:767.98px){.modal-fullscreen-md-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-md-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-md-down .modal-footer,.modal-fullscreen-md-down .modal-header{border-radius:0}.modal-fullscreen-md-down .modal-body{overflow-y:auto}}@media (max-width:991.98px){.modal-fullscreen-lg-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-lg-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-lg-down .modal-footer,.modal-fullscreen-lg-down .modal-header{border-radius:0}.modal-fullscreen-lg-down .modal-body{overflow-y:auto}}@media (max-width:1199.98px){.modal-fullscreen-xl-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-xl-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-xl-down .modal-footer,.modal-fullscreen-xl-down .modal-header{border-radius:0}.modal-fullscreen-xl-down .modal-body{overflow-y:auto}}@media (max-width:1399.98px){.modal-fullscreen-xxl-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-xxl-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-xxl-down .modal-footer,.modal-fullscreen-xxl-down .modal-header{border-radius:0}.modal-fullscreen-xxl-down .modal-body{overflow-y:auto}}.tooltip{--bs-tooltip-zindex:1080;--bs-tooltip-max-width:200px;--bs-tooltip-padding-x:0.5rem;--bs-tooltip-padding-y:0.25rem;--bs-tooltip-margin: ;--bs-tooltip-font-size:0.875rem;--bs-tooltip-color:var(--bs-body-bg);--bs-tooltip-bg:var(--bs-emphasis-color);--bs-tooltip-border-radius:var(--bs-border-radius);--bs-tooltip-opacity:0.9;--bs-tooltip-arrow-width:0.8rem;--bs-tooltip-arrow-height:0.4rem;z-index:var(--bs-tooltip-zindex);display:block;margin:var(--bs-tooltip-margin);font-family:var(--bs-font-sans-serif);font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;white-space:normal;word-spacing:normal;line-break:auto;font-size:var(--bs-tooltip-font-size);word-wrap:break-word;opacity:0}.tooltip.show{opacity:var(--bs-tooltip-opacity)}.tooltip .tooltip-arrow{display:block;width:var(--bs-tooltip-arrow-width);height:var(--bs-tooltip-arrow-height)}.tooltip .tooltip-arrow::before{position:absolute;content:"";border-color:transparent;border-style:solid}.bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow,.bs-tooltip-top .tooltip-arrow{bottom:calc(-1 * var(--bs-tooltip-arrow-height))}.bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow::before,.bs-tooltip-top .tooltip-arrow::before{top:-1px;border-width:var(--bs-tooltip-arrow-height) calc(var(--bs-tooltip-arrow-width) * .5) 0;border-top-color:var(--bs-tooltip-bg)}.bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow,.bs-tooltip-end .tooltip-arrow{left:calc(-1 * var(--bs-tooltip-arrow-height));width:var(--bs-tooltip-arrow-height);height:var(--bs-tooltip-arrow-width)}.bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow::before,.bs-tooltip-end .tooltip-arrow::before{right:-1px;border-width:calc(var(--bs-tooltip-arrow-width) * .5) var(--bs-tooltip-arrow-height) calc(var(--bs-tooltip-arrow-width) * .5) 0;border-right-color:var(--bs-tooltip-bg)}.bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow,.bs-tooltip-bottom .tooltip-arrow{top:calc(-1 * var(--bs-tooltip-arrow-height))}.bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow::before,.bs-tooltip-bottom .tooltip-arrow::before{bottom:-1px;border-width:0 calc(var(--bs-tooltip-arrow-width) * .5) var(--bs-tooltip-arrow-height);border-bottom-color:var(--bs-tooltip-bg)}.bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow,.bs-tooltip-start .tooltip-arrow{right:calc(-1 * var(--bs-tooltip-arrow-height));width:var(--bs-tooltip-arrow-height);height:var(--bs-tooltip-arrow-width)}.bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow::before,.bs-tooltip-start .tooltip-arrow::before{left:-1px;border-width:calc(var(--bs-tooltip-arrow-width) * .5) 0 calc(var(--bs-tooltip-arrow-width) * .5) var(--bs-tooltip-arrow-height);border-left-color:var(--bs-tooltip-bg)}.tooltip-inner{max-width:var(--bs-tooltip-max-width);padding:var(--bs-tooltip-padding-y) var(--bs-tooltip-padding-x);color:var(--bs-tooltip-color);text-align:center;background-color:var(--bs-tooltip-bg);border-radius:var(--bs-tooltip-border-radius)}.popover{--bs-popover-zindex:1070;--bs-popover-max-width:276px;--bs-popover-font-size:0.875rem;--bs-popover-bg:var(--bs-body-bg);--bs-popover-border-width:var(--bs-border-width);--bs-popover-border-color:var(--bs-border-color-translucent);--bs-popover-border-radius:var(--bs-border-radius-lg);--bs-popover-inner-border-radius:calc(var(--bs-border-radius-lg) - var(--bs-border-width));--bs-popover-box-shadow:var(--bs-box-shadow);--bs-popover-header-padding-x:1rem;--bs-popover-header-padding-y:0.5rem;--bs-popover-header-font-size:1rem;--bs-popover-header-color:#2fa4e7;--bs-popover-header-bg:var(--bs-secondary-bg);--bs-popover-body-padding-x:1rem;--bs-popover-body-padding-y:1rem;--bs-popover-body-color:var(--bs-body-color);--bs-popover-arrow-width:1rem;--bs-popover-arrow-height:0.5rem;--bs-popover-arrow-border:var(--bs-popover-border-color);z-index:var(--bs-popover-zindex);display:block;max-width:var(--bs-popover-max-width);font-family:var(--bs-font-sans-serif);font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;white-space:normal;word-spacing:normal;line-break:auto;font-size:var(--bs-popover-font-size);word-wrap:break-word;background-color:var(--bs-popover-bg);background-clip:padding-box;border:var(--bs-popover-border-width) solid var(--bs-popover-border-color);border-radius:var(--bs-popover-border-radius)}.popover .popover-arrow{display:block;width:var(--bs-popover-arrow-width);height:var(--bs-popover-arrow-height)}.popover .popover-arrow::after,.popover .popover-arrow::before{position:absolute;display:block;content:"";border-color:transparent;border-style:solid;border-width:0}.bs-popover-auto[data-popper-placement^=top]>.popover-arrow,.bs-popover-top>.popover-arrow{bottom:calc(-1 * (var(--bs-popover-arrow-height)) - var(--bs-popover-border-width))}.bs-popover-auto[data-popper-placement^=top]>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=top]>.popover-arrow::before,.bs-popover-top>.popover-arrow::after,.bs-popover-top>.popover-arrow::before{border-width:var(--bs-popover-arrow-height) calc(var(--bs-popover-arrow-width) * .5) 0}.bs-popover-auto[data-popper-placement^=top]>.popover-arrow::before,.bs-popover-top>.popover-arrow::before{bottom:0;border-top-color:var(--bs-popover-arrow-border)}.bs-popover-auto[data-popper-placement^=top]>.popover-arrow::after,.bs-popover-top>.popover-arrow::after{bottom:var(--bs-popover-border-width);border-top-color:var(--bs-popover-bg)}.bs-popover-auto[data-popper-placement^=right]>.popover-arrow,.bs-popover-end>.popover-arrow{left:calc(-1 * (var(--bs-popover-arrow-height)) - var(--bs-popover-border-width));width:var(--bs-popover-arrow-height);height:var(--bs-popover-arrow-width)}.bs-popover-auto[data-popper-placement^=right]>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=right]>.popover-arrow::before,.bs-popover-end>.popover-arrow::after,.bs-popover-end>.popover-arrow::before{border-width:calc(var(--bs-popover-arrow-width) * .5) var(--bs-popover-arrow-height) calc(var(--bs-popover-arrow-width) * .5) 0}.bs-popover-auto[data-popper-placement^=right]>.popover-arrow::before,.bs-popover-end>.popover-arrow::before{left:0;border-right-color:var(--bs-popover-arrow-border)}.bs-popover-auto[data-popper-placement^=right]>.popover-arrow::after,.bs-popover-end>.popover-arrow::after{left:var(--bs-popover-border-width);border-right-color:var(--bs-popover-bg)}.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow,.bs-popover-bottom>.popover-arrow{top:calc(-1 * (var(--bs-popover-arrow-height)) - var(--bs-popover-border-width))}.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow::before,.bs-popover-bottom>.popover-arrow::after,.bs-popover-bottom>.popover-arrow::before{border-width:0 calc(var(--bs-popover-arrow-width) * .5) var(--bs-popover-arrow-height)}.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow::before,.bs-popover-bottom>.popover-arrow::before{top:0;border-bottom-color:var(--bs-popover-arrow-border)}.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow::after,.bs-popover-bottom>.popover-arrow::after{top:var(--bs-popover-border-width);border-bottom-color:var(--bs-popover-bg)}.bs-popover-auto[data-popper-placement^=bottom] .popover-header::before,.bs-popover-bottom .popover-header::before{position:absolute;top:0;left:50%;display:block;width:var(--bs-popover-arrow-width);margin-left:calc(-.5 * var(--bs-popover-arrow-width));content:"";border-bottom:var(--bs-popover-border-width) solid var(--bs-popover-header-bg)}.bs-popover-auto[data-popper-placement^=left]>.popover-arrow,.bs-popover-start>.popover-arrow{right:calc(-1 * (var(--bs-popover-arrow-height)) - var(--bs-popover-border-width));width:var(--bs-popover-arrow-height);height:var(--bs-popover-arrow-width)}.bs-popover-auto[data-popper-placement^=left]>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=left]>.popover-arrow::before,.bs-popover-start>.popover-arrow::after,.bs-popover-start>.popover-arrow::before{border-width:calc(var(--bs-popover-arrow-width) * .5) 0 calc(var(--bs-popover-arrow-width) * .5) var(--bs-popover-arrow-height)}.bs-popover-auto[data-popper-placement^=left]>.popover-arrow::before,.bs-popover-start>.popover-arrow::before{right:0;border-left-color:var(--bs-popover-arrow-border)}.bs-popover-auto[data-popper-placement^=left]>.popover-arrow::after,.bs-popover-start>.popover-arrow::after{right:var(--bs-popover-border-width);border-left-color:var(--bs-popover-bg)}.popover-header{padding:var(--bs-popover-header-padding-y) var(--bs-popover-header-padding-x);margin-bottom:0;font-size:var(--bs-popover-header-font-size);color:var(--bs-popover-header-color);background-color:var(--bs-popover-header-bg);border-bottom:var(--bs-popover-border-width) solid var(--bs-popover-border-color);border-top-left-radius:var(--bs-popover-inner-border-radius);border-top-right-radius:var(--bs-popover-inner-border-radius)}.popover-header:empty{display:none}.popover-body{padding:var(--bs-popover-body-padding-y) var(--bs-popover-body-padding-x);color:var(--bs-popover-body-color)}.carousel{position:relative}.carousel.pointer-event{touch-action:pan-y}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner::after{display:block;clear:both;content:""}.carousel-item{position:relative;display:none;float:left;width:100%;margin-right:-100%;-webkit-backface-visibility:hidden;backface-visibility:hidden;transition:transform .6s ease-in-out}@media (prefers-reduced-motion:reduce){.carousel-item{transition:none}}.carousel-item-next,.carousel-item-prev,.carousel-item.active{display:block}.active.carousel-item-end,.carousel-item-next:not(.carousel-item-start){transform:translateX(100%)}.active.carousel-item-start,.carousel-item-prev:not(.carousel-item-end){transform:translateX(-100%)}.carousel-fade .carousel-item{opacity:0;transition-property:opacity;transform:none}.carousel-fade .carousel-item-next.carousel-item-start,.carousel-fade .carousel-item-prev.carousel-item-end,.carousel-fade .carousel-item.active{z-index:1;opacity:1}.carousel-fade .active.carousel-item-end,.carousel-fade .active.carousel-item-start{z-index:0;opacity:0;transition:opacity 0s .6s}@media (prefers-reduced-motion:reduce){.carousel-fade .active.carousel-item-end,.carousel-fade .active.carousel-item-start{transition:none}}.carousel-control-next,.carousel-control-prev{position:absolute;top:0;bottom:0;z-index:1;display:flex;align-items:center;justify-content:center;width:15%;padding:0;color:#fff;text-align:center;background:0 0;border:0;opacity:.5;transition:opacity .15s ease}@media (prefers-reduced-motion:reduce){.carousel-control-next,.carousel-control-prev{transition:none}}.carousel-control-next:focus,.carousel-control-next:hover,.carousel-control-prev:focus,.carousel-control-prev:hover{color:#fff;text-decoration:none;outline:0;opacity:.9}.carousel-control-prev{left:0}.carousel-control-next{right:0}.carousel-control-next-icon,.carousel-control-prev-icon{display:inline-block;width:2rem;height:2rem;background-repeat:no-repeat;background-position:50%;background-size:100% 100%}.carousel-control-prev-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e")}.carousel-control-next-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e")}.carousel-indicators{position:absolute;right:0;bottom:0;left:0;z-index:2;display:flex;justify-content:center;padding:0;margin-right:15%;margin-bottom:1rem;margin-left:15%}.carousel-indicators [data-bs-target]{box-sizing:content-box;flex:0 1 auto;width:30px;height:3px;padding:0;margin-right:3px;margin-left:3px;text-indent:-999px;cursor:pointer;background-color:#fff;background-clip:padding-box;border:0;border-top:10px solid transparent;border-bottom:10px solid transparent;opacity:.5;transition:opacity .6s ease}@media (prefers-reduced-motion:reduce){.carousel-indicators [data-bs-target]{transition:none}}.carousel-indicators .active{opacity:1}.carousel-caption{position:absolute;right:15%;bottom:1.25rem;left:15%;padding-top:1.25rem;padding-bottom:1.25rem;color:#fff;text-align:center}.carousel-dark .carousel-control-next-icon,.carousel-dark .carousel-control-prev-icon{filter:invert(1) grayscale(100)}.carousel-dark .carousel-indicators [data-bs-target]{background-color:#000}.carousel-dark .carousel-caption{color:#000}[data-bs-theme=dark] .carousel .carousel-control-next-icon,[data-bs-theme=dark] .carousel .carousel-control-prev-icon,[data-bs-theme=dark].carousel .carousel-control-next-icon,[data-bs-theme=dark].carousel .carousel-control-prev-icon{filter:invert(1) grayscale(100)}[data-bs-theme=dark] .carousel .carousel-indicators [data-bs-target],[data-bs-theme=dark].carousel .carousel-indicators [data-bs-target]{background-color:#000}[data-bs-theme=dark] .carousel .carousel-caption,[data-bs-theme=dark].carousel .carousel-caption{color:#000}.spinner-border,.spinner-grow{display:inline-block;width:var(--bs-spinner-width);height:var(--bs-spinner-height);vertical-align:var(--bs-spinner-vertical-align);border-radius:50%;animation:var(--bs-spinner-animation-speed) linear infinite var(--bs-spinner-animation-name)}@keyframes spinner-border{to{transform:rotate(360deg)}}.spinner-border{--bs-spinner-width:2rem;--bs-spinner-height:2rem;--bs-spinner-vertical-align:-0.125em;--bs-spinner-border-width:0.25em;--bs-spinner-animation-speed:0.75s;--bs-spinner-animation-name:spinner-border;border:var(--bs-spinner-border-width) solid currentcolor;border-right-color:transparent}.spinner-border-sm{--bs-spinner-width:1rem;--bs-spinner-height:1rem;--bs-spinner-border-width:0.2em}@keyframes spinner-grow{0%{transform:scale(0)}50%{opacity:1;transform:none}}.spinner-grow{--bs-spinner-width:2rem;--bs-spinner-height:2rem;--bs-spinner-vertical-align:-0.125em;--bs-spinner-animation-speed:0.75s;--bs-spinner-animation-name:spinner-grow;background-color:currentcolor;opacity:0}.spinner-grow-sm{--bs-spinner-width:1rem;--bs-spinner-height:1rem}@media (prefers-reduced-motion:reduce){.spinner-border,.spinner-grow{--bs-spinner-animation-speed:1.5s}}.offcanvas,.offcanvas-lg,.offcanvas-md,.offcanvas-sm,.offcanvas-xl,.offcanvas-xxl{--bs-offcanvas-zindex:1045;--bs-offcanvas-width:400px;--bs-offcanvas-height:30vh;--bs-offcanvas-padding-x:1rem;--bs-offcanvas-padding-y:1rem;--bs-offcanvas-color:var(--bs-body-color);--bs-offcanvas-bg:var(--bs-body-bg);--bs-offcanvas-border-width:var(--bs-border-width);--bs-offcanvas-border-color:var(--bs-border-color-translucent);--bs-offcanvas-box-shadow:var(--bs-box-shadow-sm);--bs-offcanvas-transition:transform 0.3s ease-in-out;--bs-offcanvas-title-line-height:1.5}@media (max-width:575.98px){.offcanvas-sm{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;transition:var(--bs-offcanvas-transition)}}@media (max-width:575.98px) and (prefers-reduced-motion:reduce){.offcanvas-sm{transition:none}}@media (max-width:575.98px){.offcanvas-sm.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(-100%)}.offcanvas-sm.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(100%)}.offcanvas-sm.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}.offcanvas-sm.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}.offcanvas-sm.show:not(.hiding),.offcanvas-sm.showing{transform:none}.offcanvas-sm.hiding,.offcanvas-sm.show,.offcanvas-sm.showing{visibility:visible}}@media (min-width:576px){.offcanvas-sm{--bs-offcanvas-height:auto;--bs-offcanvas-border-width:0;background-color:transparent!important}.offcanvas-sm .offcanvas-header{display:none}.offcanvas-sm .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible;background-color:transparent!important}}@media (max-width:767.98px){.offcanvas-md{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;transition:var(--bs-offcanvas-transition)}}@media (max-width:767.98px) and (prefers-reduced-motion:reduce){.offcanvas-md{transition:none}}@media (max-width:767.98px){.offcanvas-md.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(-100%)}.offcanvas-md.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(100%)}.offcanvas-md.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}.offcanvas-md.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}.offcanvas-md.show:not(.hiding),.offcanvas-md.showing{transform:none}.offcanvas-md.hiding,.offcanvas-md.show,.offcanvas-md.showing{visibility:visible}}@media (min-width:768px){.offcanvas-md{--bs-offcanvas-height:auto;--bs-offcanvas-border-width:0;background-color:transparent!important}.offcanvas-md .offcanvas-header{display:none}.offcanvas-md .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible;background-color:transparent!important}}@media (max-width:991.98px){.offcanvas-lg{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;transition:var(--bs-offcanvas-transition)}}@media (max-width:991.98px) and (prefers-reduced-motion:reduce){.offcanvas-lg{transition:none}}@media (max-width:991.98px){.offcanvas-lg.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(-100%)}.offcanvas-lg.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(100%)}.offcanvas-lg.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}.offcanvas-lg.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}.offcanvas-lg.show:not(.hiding),.offcanvas-lg.showing{transform:none}.offcanvas-lg.hiding,.offcanvas-lg.show,.offcanvas-lg.showing{visibility:visible}}@media (min-width:992px){.offcanvas-lg{--bs-offcanvas-height:auto;--bs-offcanvas-border-width:0;background-color:transparent!important}.offcanvas-lg .offcanvas-header{display:none}.offcanvas-lg .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible;background-color:transparent!important}}@media (max-width:1199.98px){.offcanvas-xl{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;transition:var(--bs-offcanvas-transition)}}@media (max-width:1199.98px) and (prefers-reduced-motion:reduce){.offcanvas-xl{transition:none}}@media (max-width:1199.98px){.offcanvas-xl.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(-100%)}.offcanvas-xl.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(100%)}.offcanvas-xl.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}.offcanvas-xl.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}.offcanvas-xl.show:not(.hiding),.offcanvas-xl.showing{transform:none}.offcanvas-xl.hiding,.offcanvas-xl.show,.offcanvas-xl.showing{visibility:visible}}@media (min-width:1200px){.offcanvas-xl{--bs-offcanvas-height:auto;--bs-offcanvas-border-width:0;background-color:transparent!important}.offcanvas-xl .offcanvas-header{display:none}.offcanvas-xl .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible;background-color:transparent!important}}@media (max-width:1399.98px){.offcanvas-xxl{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;transition:var(--bs-offcanvas-transition)}}@media (max-width:1399.98px) and (prefers-reduced-motion:reduce){.offcanvas-xxl{transition:none}}@media (max-width:1399.98px){.offcanvas-xxl.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(-100%)}.offcanvas-xxl.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(100%)}.offcanvas-xxl.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}.offcanvas-xxl.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}.offcanvas-xxl.show:not(.hiding),.offcanvas-xxl.showing{transform:none}.offcanvas-xxl.hiding,.offcanvas-xxl.show,.offcanvas-xxl.showing{visibility:visible}}@media (min-width:1400px){.offcanvas-xxl{--bs-offcanvas-height:auto;--bs-offcanvas-border-width:0;background-color:transparent!important}.offcanvas-xxl .offcanvas-header{display:none}.offcanvas-xxl .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible;background-color:transparent!important}}.offcanvas{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;transition:var(--bs-offcanvas-transition)}@media (prefers-reduced-motion:reduce){.offcanvas{transition:none}}.offcanvas.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(-100%)}.offcanvas.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(100%)}.offcanvas.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}.offcanvas.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}.offcanvas.show:not(.hiding),.offcanvas.showing{transform:none}.offcanvas.hiding,.offcanvas.show,.offcanvas.showing{visibility:visible}.offcanvas-backdrop{position:fixed;top:0;left:0;z-index:1040;width:100vw;height:100vh;background-color:#000}.offcanvas-backdrop.fade{opacity:0}.offcanvas-backdrop.show{opacity:.5}.offcanvas-header{display:flex;align-items:center;justify-content:space-between;padding:var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x)}.offcanvas-header .btn-close{padding:calc(var(--bs-offcanvas-padding-y) * .5) calc(var(--bs-offcanvas-padding-x) * .5);margin-top:calc(-.5 * var(--bs-offcanvas-padding-y));margin-right:calc(-.5 * var(--bs-offcanvas-padding-x));margin-bottom:calc(-.5 * var(--bs-offcanvas-padding-y))}.offcanvas-title{margin-bottom:0;line-height:var(--bs-offcanvas-title-line-height)}.offcanvas-body{flex-grow:1;padding:var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x);overflow-y:auto}.placeholder{display:inline-block;min-height:1em;vertical-align:middle;cursor:wait;background-color:currentcolor;opacity:.5}.placeholder.btn::before{display:inline-block;content:""}.placeholder-xs{min-height:.6em}.placeholder-sm{min-height:.8em}.placeholder-lg{min-height:1.2em}.placeholder-glow .placeholder{animation:placeholder-glow 2s ease-in-out infinite}@keyframes placeholder-glow{50%{opacity:.2}}.placeholder-wave{-webkit-mask-image:linear-gradient(130deg,#000 55%,rgba(0,0,0,0.8) 75%,#000 95%);mask-image:linear-gradient(130deg,#000 55%,rgba(0,0,0,0.8) 75%,#000 95%);-webkit-mask-size:200% 100%;mask-size:200% 100%;animation:placeholder-wave 2s linear infinite}@keyframes placeholder-wave{100%{-webkit-mask-position:-200% 0%;mask-position:-200% 0%}}.clearfix::after{display:block;clear:both;content:""}.text-bg-primary{color:#fff!important;background-color:RGBA(var(--bs-primary-rgb),var(--bs-bg-opacity,1))!important}.text-bg-secondary{color:#000!important;background-color:RGBA(var(--bs-secondary-rgb),var(--bs-bg-opacity,1))!important}.text-bg-success{color:#fff!important;background-color:RGBA(var(--bs-success-rgb),var(--bs-bg-opacity,1))!important}.text-bg-info{color:#fff!important;background-color:RGBA(var(--bs-info-rgb),var(--bs-bg-opacity,1))!important}.text-bg-warning{color:#fff!important;background-color:RGBA(var(--bs-warning-rgb),var(--bs-bg-opacity,1))!important}.text-bg-danger{color:#fff!important;background-color:RGBA(var(--bs-danger-rgb),var(--bs-bg-opacity,1))!important}.text-bg-light{color:#000!important;background-color:RGBA(var(--bs-light-rgb),var(--bs-bg-opacity,1))!important}.text-bg-dark{color:#fff!important;background-color:RGBA(var(--bs-dark-rgb),var(--bs-bg-opacity,1))!important}.link-primary{color:RGBA(var(--bs-primary-rgb),var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(var(--bs-primary-rgb),var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(var(--bs-primary-rgb),var(--bs-link-underline-opacity,1))!important}.link-primary:focus,.link-primary:hover{color:RGBA(38,131,185,var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(38,131,185,var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(38,131,185,var(--bs-link-underline-opacity,1))!important}.link-secondary{color:RGBA(var(--bs-secondary-rgb),var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(var(--bs-secondary-rgb),var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(var(--bs-secondary-rgb),var(--bs-link-underline-opacity,1))!important}.link-secondary:focus,.link-secondary:hover{color:RGBA(237,240,242,var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(237,240,242,var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(237,240,242,var(--bs-link-underline-opacity,1))!important}.link-success{color:RGBA(var(--bs-success-rgb),var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(var(--bs-success-rgb),var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(var(--bs-success-rgb),var(--bs-link-underline-opacity,1))!important}.link-success:focus,.link-success:hover{color:RGBA(92,134,46,var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(92,134,46,var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(92,134,46,var(--bs-link-underline-opacity,1))!important}.link-info{color:RGBA(var(--bs-info-rgb),var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(var(--bs-info-rgb),var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(var(--bs-info-rgb),var(--bs-link-underline-opacity,1))!important}.link-info:focus,.link-info:hover{color:RGBA(2,48,92,var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(2,48,92,var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(2,48,92,var(--bs-link-underline-opacity,1))!important}.link-warning{color:RGBA(var(--bs-warning-rgb),var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(var(--bs-warning-rgb),var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(var(--bs-warning-rgb),var(--bs-link-underline-opacity,1))!important}.link-warning:focus,.link-warning:hover{color:RGBA(177,69,0,var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(177,69,0,var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(177,69,0,var(--bs-link-underline-opacity,1))!important}.link-danger{color:RGBA(var(--bs-danger-rgb),var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(var(--bs-danger-rgb),var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(var(--bs-danger-rgb),var(--bs-link-underline-opacity,1))!important}.link-danger:focus,.link-danger:hover{color:RGBA(159,22,27,var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(159,22,27,var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(159,22,27,var(--bs-link-underline-opacity,1))!important}.link-light{color:RGBA(var(--bs-light-rgb),var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(var(--bs-light-rgb),var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(var(--bs-light-rgb),var(--bs-link-underline-opacity,1))!important}.link-light:focus,.link-light:hover{color:RGBA(249,250,251,var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(249,250,251,var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(249,250,251,var(--bs-link-underline-opacity,1))!important}.link-dark{color:RGBA(var(--bs-dark-rgb),var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(var(--bs-dark-rgb),var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(var(--bs-dark-rgb),var(--bs-link-underline-opacity,1))!important}.link-dark:focus,.link-dark:hover{color:RGBA(42,46,51,var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(42,46,51,var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(42,46,51,var(--bs-link-underline-opacity,1))!important}.link-body-emphasis{color:RGBA(var(--bs-emphasis-color-rgb),var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(var(--bs-emphasis-color-rgb),var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(var(--bs-emphasis-color-rgb),var(--bs-link-underline-opacity,1))!important}.link-body-emphasis:focus,.link-body-emphasis:hover{color:RGBA(var(--bs-emphasis-color-rgb),var(--bs-link-opacity,.75))!important;-webkit-text-decoration-color:RGBA(var(--bs-emphasis-color-rgb),var(--bs-link-underline-opacity,0.75))!important;text-decoration-color:RGBA(var(--bs-emphasis-color-rgb),var(--bs-link-underline-opacity,0.75))!important}.focus-ring:focus{outline:0;box-shadow:var(--bs-focus-ring-x,0) var(--bs-focus-ring-y,0) var(--bs-focus-ring-blur,0) var(--bs-focus-ring-width) var(--bs-focus-ring-color)}.icon-link{display:inline-flex;gap:.375rem;align-items:center;-webkit-text-decoration-color:rgba(var(--bs-link-color-rgb),var(--bs-link-opacity,0.5));text-decoration-color:rgba(var(--bs-link-color-rgb),var(--bs-link-opacity,0.5));text-underline-offset:0.25em;-webkit-backface-visibility:hidden;backface-visibility:hidden}.icon-link>.bi{flex-shrink:0;width:1em;height:1em;fill:currentcolor;transition:.2s ease-in-out transform}@media (prefers-reduced-motion:reduce){.icon-link>.bi{transition:none}}.icon-link-hover:focus-visible>.bi,.icon-link-hover:hover>.bi{transform:var(--bs-icon-link-transform,translate3d(.25em,0,0))}.ratio{position:relative;width:100%}.ratio::before{display:block;padding-top:var(--bs-aspect-ratio);content:""}.ratio>*{position:absolute;top:0;left:0;width:100%;height:100%}.ratio-1x1{--bs-aspect-ratio:100%}.ratio-4x3{--bs-aspect-ratio:75%}.ratio-16x9{--bs-aspect-ratio:56.25%}.ratio-21x9{--bs-aspect-ratio:42.8571428571%}.fixed-top{position:fixed;top:0;right:0;left:0;z-index:1030}.fixed-bottom{position:fixed;right:0;bottom:0;left:0;z-index:1030}.sticky-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}.sticky-bottom{position:-webkit-sticky;position:sticky;bottom:0;z-index:1020}@media (min-width:576px){.sticky-sm-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}.sticky-sm-bottom{position:-webkit-sticky;position:sticky;bottom:0;z-index:1020}}@media (min-width:768px){.sticky-md-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}.sticky-md-bottom{position:-webkit-sticky;position:sticky;bottom:0;z-index:1020}}@media (min-width:992px){.sticky-lg-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}.sticky-lg-bottom{position:-webkit-sticky;position:sticky;bottom:0;z-index:1020}}@media (min-width:1200px){.sticky-xl-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}.sticky-xl-bottom{position:-webkit-sticky;position:sticky;bottom:0;z-index:1020}}@media (min-width:1400px){.sticky-xxl-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}.sticky-xxl-bottom{position:-webkit-sticky;position:sticky;bottom:0;z-index:1020}}.hstack{display:flex;flex-direction:row;align-items:center;align-self:stretch}.vstack{display:flex;flex:1 1 auto;flex-direction:column;align-self:stretch}.visually-hidden,.visually-hidden-focusable:not(:focus):not(:focus-within){width:1px!important;height:1px!important;padding:0!important;margin:-1px!important;overflow:hidden!important;clip:rect(0,0,0,0)!important;white-space:nowrap!important;border:0!important}.visually-hidden-focusable:not(:focus):not(:focus-within):not(caption),.visually-hidden:not(caption){position:absolute!important}.stretched-link::after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;content:""}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.vr{display:inline-block;align-self:stretch;width:var(--bs-border-width);min-height:1em;background-color:currentcolor;opacity:.25}.align-baseline{vertical-align:baseline!important}.align-top{vertical-align:top!important}.align-middle{vertical-align:middle!important}.align-bottom{vertical-align:bottom!important}.align-text-bottom{vertical-align:text-bottom!important}.align-text-top{vertical-align:text-top!important}.float-start{float:left!important}.float-end{float:right!important}.float-none{float:none!important}.object-fit-contain{-o-object-fit:contain!important;object-fit:contain!important}.object-fit-cover{-o-object-fit:cover!important;object-fit:cover!important}.object-fit-fill{-o-object-fit:fill!important;object-fit:fill!important}.object-fit-scale{-o-object-fit:scale-down!important;object-fit:scale-down!important}.object-fit-none{-o-object-fit:none!important;object-fit:none!important}.opacity-0{opacity:0!important}.opacity-25{opacity:.25!important}.opacity-50{opacity:.5!important}.opacity-75{opacity:.75!important}.opacity-100{opacity:1!important}.overflow-auto{overflow:auto!important}.overflow-hidden{overflow:hidden!important}.overflow-visible{overflow:visible!important}.overflow-scroll{overflow:scroll!important}.overflow-x-auto{overflow-x:auto!important}.overflow-x-hidden{overflow-x:hidden!important}.overflow-x-visible{overflow-x:visible!important}.overflow-x-scroll{overflow-x:scroll!important}.overflow-y-auto{overflow-y:auto!important}.overflow-y-hidden{overflow-y:hidden!important}.overflow-y-visible{overflow-y:visible!important}.overflow-y-scroll{overflow-y:scroll!important}.d-inline{display:inline!important}.d-inline-block{display:inline-block!important}.d-block{display:block!important}.d-grid{display:grid!important}.d-inline-grid{display:inline-grid!important}.d-table{display:table!important}.d-table-row{display:table-row!important}.d-table-cell{display:table-cell!important}.d-flex{display:flex!important}.d-inline-flex{display:inline-flex!important}.d-none{display:none!important}.shadow{box-shadow:var(--bs-box-shadow)!important}.shadow-sm{box-shadow:var(--bs-box-shadow-sm)!important}.shadow-lg{box-shadow:var(--bs-box-shadow-lg)!important}.shadow-none{box-shadow:none!important}.focus-ring-primary{--bs-focus-ring-color:rgba(var(--bs-primary-rgb), var(--bs-focus-ring-opacity))}.focus-ring-secondary{--bs-focus-ring-color:rgba(var(--bs-secondary-rgb), var(--bs-focus-ring-opacity))}.focus-ring-success{--bs-focus-ring-color:rgba(var(--bs-success-rgb), var(--bs-focus-ring-opacity))}.focus-ring-info{--bs-focus-ring-color:rgba(var(--bs-info-rgb), var(--bs-focus-ring-opacity))}.focus-ring-warning{--bs-focus-ring-color:rgba(var(--bs-warning-rgb), var(--bs-focus-ring-opacity))}.focus-ring-danger{--bs-focus-ring-color:rgba(var(--bs-danger-rgb), var(--bs-focus-ring-opacity))}.focus-ring-light{--bs-focus-ring-color:rgba(var(--bs-light-rgb), var(--bs-focus-ring-opacity))}.focus-ring-dark{--bs-focus-ring-color:rgba(var(--bs-dark-rgb), var(--bs-focus-ring-opacity))}.position-static{position:static!important}.position-relative{position:relative!important}.position-absolute{position:absolute!important}.position-fixed{position:fixed!important}.position-sticky{position:-webkit-sticky!important;position:sticky!important}.top-0{top:0!important}.top-50{top:50%!important}.top-100{top:100%!important}.bottom-0{bottom:0!important}.bottom-50{bottom:50%!important}.bottom-100{bottom:100%!important}.start-0{left:0!important}.start-50{left:50%!important}.start-100{left:100%!important}.end-0{right:0!important}.end-50{right:50%!important}.end-100{right:100%!important}.translate-middle{transform:translate(-50%,-50%)!important}.translate-middle-x{transform:translateX(-50%)!important}.translate-middle-y{transform:translateY(-50%)!important}.border{border:var(--bs-border-width) var(--bs-border-style) var(--bs-border-color)!important}.border-0{border:0!important}.border-top{border-top:var(--bs-border-width) var(--bs-border-style) var(--bs-border-color)!important}.border-top-0{border-top:0!important}.border-end{border-right:var(--bs-border-width) var(--bs-border-style) var(--bs-border-color)!important}.border-end-0{border-right:0!important}.border-bottom{border-bottom:var(--bs-border-width) var(--bs-border-style) var(--bs-border-color)!important}.border-bottom-0{border-bottom:0!important}.border-start{border-left:var(--bs-border-width) var(--bs-border-style) var(--bs-border-color)!important}.border-start-0{border-left:0!important}.border-primary{--bs-border-opacity:1;border-color:rgba(var(--bs-primary-rgb),var(--bs-border-opacity))!important}.border-secondary{--bs-border-opacity:1;border-color:rgba(var(--bs-secondary-rgb),var(--bs-border-opacity))!important}.border-success{--bs-border-opacity:1;border-color:rgba(var(--bs-success-rgb),var(--bs-border-opacity))!important}.border-info{--bs-border-opacity:1;border-color:rgba(var(--bs-info-rgb),var(--bs-border-opacity))!important}.border-warning{--bs-border-opacity:1;border-color:rgba(var(--bs-warning-rgb),var(--bs-border-opacity))!important}.border-danger{--bs-border-opacity:1;border-color:rgba(var(--bs-danger-rgb),var(--bs-border-opacity))!important}.border-light{--bs-border-opacity:1;border-color:rgba(var(--bs-light-rgb),var(--bs-border-opacity))!important}.border-dark{--bs-border-opacity:1;border-color:rgba(var(--bs-dark-rgb),var(--bs-border-opacity))!important}.border-black{--bs-border-opacity:1;border-color:rgba(var(--bs-black-rgb),var(--bs-border-opacity))!important}.border-white{--bs-border-opacity:1;border-color:rgba(var(--bs-white-rgb),var(--bs-border-opacity))!important}.border-primary-subtle{border-color:var(--bs-primary-border-subtle)!important}.border-secondary-subtle{border-color:var(--bs-secondary-border-subtle)!important}.border-success-subtle{border-color:var(--bs-success-border-subtle)!important}.border-info-subtle{border-color:var(--bs-info-border-subtle)!important}.border-warning-subtle{border-color:var(--bs-warning-border-subtle)!important}.border-danger-subtle{border-color:var(--bs-danger-border-subtle)!important}.border-light-subtle{border-color:var(--bs-light-border-subtle)!important}.border-dark-subtle{border-color:var(--bs-dark-border-subtle)!important}.border-1{border-width:1px!important}.border-2{border-width:2px!important}.border-3{border-width:3px!important}.border-4{border-width:4px!important}.border-5{border-width:5px!important}.border-opacity-10{--bs-border-opacity:0.1}.border-opacity-25{--bs-border-opacity:0.25}.border-opacity-50{--bs-border-opacity:0.5}.border-opacity-75{--bs-border-opacity:0.75}.border-opacity-100{--bs-border-opacity:1}.w-25{width:25%!important}.w-50{width:50%!important}.w-75{width:75%!important}.w-100{width:100%!important}.w-auto{width:auto!important}.mw-100{max-width:100%!important}.vw-100{width:100vw!important}.min-vw-100{min-width:100vw!important}.h-25{height:25%!important}.h-50{height:50%!important}.h-75{height:75%!important}.h-100{height:100%!important}.h-auto{height:auto!important}.mh-100{max-height:100%!important}.vh-100{height:100vh!important}.min-vh-100{min-height:100vh!important}.flex-fill{flex:1 1 auto!important}.flex-row{flex-direction:row!important}.flex-column{flex-direction:column!important}.flex-row-reverse{flex-direction:row-reverse!important}.flex-column-reverse{flex-direction:column-reverse!important}.flex-grow-0{flex-grow:0!important}.flex-grow-1{flex-grow:1!important}.flex-shrink-0{flex-shrink:0!important}.flex-shrink-1{flex-shrink:1!important}.flex-wrap{flex-wrap:wrap!important}.flex-nowrap{flex-wrap:nowrap!important}.flex-wrap-reverse{flex-wrap:wrap-reverse!important}.justify-content-start{justify-content:flex-start!important}.justify-content-end{justify-content:flex-end!important}.justify-content-center{justify-content:center!important}.justify-content-between{justify-content:space-between!important}.justify-content-around{justify-content:space-around!important}.justify-content-evenly{justify-content:space-evenly!important}.align-items-start{align-items:flex-start!important}.align-items-end{align-items:flex-end!important}.align-items-center{align-items:center!important}.align-items-baseline{align-items:baseline!important}.align-items-stretch{align-items:stretch!important}.align-content-start{align-content:flex-start!important}.align-content-end{align-content:flex-end!important}.align-content-center{align-content:center!important}.align-content-between{align-content:space-between!important}.align-content-around{align-content:space-around!important}.align-content-stretch{align-content:stretch!important}.align-self-auto{align-self:auto!important}.align-self-start{align-self:flex-start!important}.align-self-end{align-self:flex-end!important}.align-self-center{align-self:center!important}.align-self-baseline{align-self:baseline!important}.align-self-stretch{align-self:stretch!important}.order-first{order:-1!important}.order-0{order:0!important}.order-1{order:1!important}.order-2{order:2!important}.order-3{order:3!important}.order-4{order:4!important}.order-5{order:5!important}.order-last{order:6!important}.m-0{margin:0!important}.m-1{margin:.25rem!important}.m-2{margin:.5rem!important}.m-3{margin:1rem!important}.m-4{margin:1.5rem!important}.m-5{margin:3rem!important}.m-auto{margin:auto!important}.mx-0{margin-right:0!important;margin-left:0!important}.mx-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-3{margin-right:1rem!important;margin-left:1rem!important}.mx-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-5{margin-right:3rem!important;margin-left:3rem!important}.mx-auto{margin-right:auto!important;margin-left:auto!important}.my-0{margin-top:0!important;margin-bottom:0!important}.my-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-0{margin-top:0!important}.mt-1{margin-top:.25rem!important}.mt-2{margin-top:.5rem!important}.mt-3{margin-top:1rem!important}.mt-4{margin-top:1.5rem!important}.mt-5{margin-top:3rem!important}.mt-auto{margin-top:auto!important}.me-0{margin-right:0!important}.me-1{margin-right:.25rem!important}.me-2{margin-right:.5rem!important}.me-3{margin-right:1rem!important}.me-4{margin-right:1.5rem!important}.me-5{margin-right:3rem!important}.me-auto{margin-right:auto!important}.mb-0{margin-bottom:0!important}.mb-1{margin-bottom:.25rem!important}.mb-2{margin-bottom:.5rem!important}.mb-3{margin-bottom:1rem!important}.mb-4{margin-bottom:1.5rem!important}.mb-5{margin-bottom:3rem!important}.mb-auto{margin-bottom:auto!important}.ms-0{margin-left:0!important}.ms-1{margin-left:.25rem!important}.ms-2{margin-left:.5rem!important}.ms-3{margin-left:1rem!important}.ms-4{margin-left:1.5rem!important}.ms-5{margin-left:3rem!important}.ms-auto{margin-left:auto!important}.p-0{padding:0!important}.p-1{padding:.25rem!important}.p-2{padding:.5rem!important}.p-3{padding:1rem!important}.p-4{padding:1.5rem!important}.p-5{padding:3rem!important}.px-0{padding-right:0!important;padding-left:0!important}.px-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-3{padding-right:1rem!important;padding-left:1rem!important}.px-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-5{padding-right:3rem!important;padding-left:3rem!important}.py-0{padding-top:0!important;padding-bottom:0!important}.py-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-0{padding-top:0!important}.pt-1{padding-top:.25rem!important}.pt-2{padding-top:.5rem!important}.pt-3{padding-top:1rem!important}.pt-4{padding-top:1.5rem!important}.pt-5{padding-top:3rem!important}.pe-0{padding-right:0!important}.pe-1{padding-right:.25rem!important}.pe-2{padding-right:.5rem!important}.pe-3{padding-right:1rem!important}.pe-4{padding-right:1.5rem!important}.pe-5{padding-right:3rem!important}.pb-0{padding-bottom:0!important}.pb-1{padding-bottom:.25rem!important}.pb-2{padding-bottom:.5rem!important}.pb-3{padding-bottom:1rem!important}.pb-4{padding-bottom:1.5rem!important}.pb-5{padding-bottom:3rem!important}.ps-0{padding-left:0!important}.ps-1{padding-left:.25rem!important}.ps-2{padding-left:.5rem!important}.ps-3{padding-left:1rem!important}.ps-4{padding-left:1.5rem!important}.ps-5{padding-left:3rem!important}.gap-0{gap:0!important}.gap-1{gap:.25rem!important}.gap-2{gap:.5rem!important}.gap-3{gap:1rem!important}.gap-4{gap:1.5rem!important}.gap-5{gap:3rem!important}.row-gap-0{row-gap:0!important}.row-gap-1{row-gap:.25rem!important}.row-gap-2{row-gap:.5rem!important}.row-gap-3{row-gap:1rem!important}.row-gap-4{row-gap:1.5rem!important}.row-gap-5{row-gap:3rem!important}.column-gap-0{-moz-column-gap:0!important;column-gap:0!important}.column-gap-1{-moz-column-gap:0.25rem!important;column-gap:.25rem!important}.column-gap-2{-moz-column-gap:0.5rem!important;column-gap:.5rem!important}.column-gap-3{-moz-column-gap:1rem!important;column-gap:1rem!important}.column-gap-4{-moz-column-gap:1.5rem!important;column-gap:1.5rem!important}.column-gap-5{-moz-column-gap:3rem!important;column-gap:3rem!important}.font-monospace{font-family:var(--bs-font-monospace)!important}.fs-1{font-size:calc(1.375rem + 1.5vw)!important}.fs-2{font-size:calc(1.325rem + .9vw)!important}.fs-3{font-size:calc(1.3rem + .6vw)!important}.fs-4{font-size:calc(1.275rem + .3vw)!important}.fs-5{font-size:1.25rem!important}.fs-6{font-size:1rem!important}.fst-italic{font-style:italic!important}.fst-normal{font-style:normal!important}.fw-lighter{font-weight:lighter!important}.fw-light{font-weight:300!important}.fw-normal{font-weight:400!important}.fw-medium{font-weight:500!important}.fw-semibold{font-weight:600!important}.fw-bold{font-weight:700!important}.fw-bolder{font-weight:bolder!important}.lh-1{line-height:1!important}.lh-sm{line-height:1.25!important}.lh-base{line-height:1.5!important}.lh-lg{line-height:2!important}.text-start{text-align:left!important}.text-end{text-align:right!important}.text-center{text-align:center!important}.text-decoration-none{text-decoration:none!important}.text-decoration-underline{text-decoration:underline!important}.text-decoration-line-through{text-decoration:line-through!important}.text-lowercase{text-transform:lowercase!important}.text-uppercase{text-transform:uppercase!important}.text-capitalize{text-transform:capitalize!important}.text-wrap{white-space:normal!important}.text-nowrap{white-space:nowrap!important}.text-break{word-wrap:break-word!important;word-break:break-word!important}.text-primary{--bs-text-opacity:1;color:rgba(var(--bs-primary-rgb),var(--bs-text-opacity))!important}.text-secondary{--bs-text-opacity:1;color:rgba(var(--bs-secondary-rgb),var(--bs-text-opacity))!important}.text-success{--bs-text-opacity:1;color:rgba(var(--bs-success-rgb),var(--bs-text-opacity))!important}.text-info{--bs-text-opacity:1;color:rgba(var(--bs-info-rgb),var(--bs-text-opacity))!important}.text-warning{--bs-text-opacity:1;color:rgba(var(--bs-warning-rgb),var(--bs-text-opacity))!important}.text-danger{--bs-text-opacity:1;color:rgba(var(--bs-danger-rgb),var(--bs-text-opacity))!important}.text-light{--bs-text-opacity:1;color:rgba(var(--bs-light-rgb),var(--bs-text-opacity))!important}.text-dark{--bs-text-opacity:1;color:rgba(var(--bs-dark-rgb),var(--bs-text-opacity))!important}.text-black{--bs-text-opacity:1;color:rgba(var(--bs-black-rgb),var(--bs-text-opacity))!important}.text-white{--bs-text-opacity:1;color:rgba(var(--bs-white-rgb),var(--bs-text-opacity))!important}.text-body{--bs-text-opacity:1;color:rgba(var(--bs-body-color-rgb),var(--bs-text-opacity))!important}.text-muted{--bs-text-opacity:1;color:var(--bs-secondary-color)!important}.text-black-50{--bs-text-opacity:1;color:rgba(0,0,0,.5)!important}.text-white-50{--bs-text-opacity:1;color:rgba(255,255,255,.5)!important}.text-body-secondary{--bs-text-opacity:1;color:var(--bs-secondary-color)!important}.text-body-tertiary{--bs-text-opacity:1;color:var(--bs-tertiary-color)!important}.text-body-emphasis{--bs-text-opacity:1;color:var(--bs-emphasis-color)!important}.text-reset{--bs-text-opacity:1;color:inherit!important}.text-opacity-25{--bs-text-opacity:0.25}.text-opacity-50{--bs-text-opacity:0.5}.text-opacity-75{--bs-text-opacity:0.75}.text-opacity-100{--bs-text-opacity:1}.text-primary-emphasis{color:var(--bs-primary-text-emphasis)!important}.text-secondary-emphasis{color:var(--bs-secondary-text-emphasis)!important}.text-success-emphasis{color:var(--bs-success-text-emphasis)!important}.text-info-emphasis{color:var(--bs-info-text-emphasis)!important}.text-warning-emphasis{color:var(--bs-warning-text-emphasis)!important}.text-danger-emphasis{color:var(--bs-danger-text-emphasis)!important}.text-light-emphasis{color:var(--bs-light-text-emphasis)!important}.text-dark-emphasis{color:var(--bs-dark-text-emphasis)!important}.link-opacity-10{--bs-link-opacity:0.1}.link-opacity-10-hover:hover{--bs-link-opacity:0.1}.link-opacity-25{--bs-link-opacity:0.25}.link-opacity-25-hover:hover{--bs-link-opacity:0.25}.link-opacity-50{--bs-link-opacity:0.5}.link-opacity-50-hover:hover{--bs-link-opacity:0.5}.link-opacity-75{--bs-link-opacity:0.75}.link-opacity-75-hover:hover{--bs-link-opacity:0.75}.link-opacity-100{--bs-link-opacity:1}.link-opacity-100-hover:hover{--bs-link-opacity:1}.link-offset-1{text-underline-offset:0.125em!important}.link-offset-1-hover:hover{text-underline-offset:0.125em!important}.link-offset-2{text-underline-offset:0.25em!important}.link-offset-2-hover:hover{text-underline-offset:0.25em!important}.link-offset-3{text-underline-offset:0.375em!important}.link-offset-3-hover:hover{text-underline-offset:0.375em!important}.link-underline-primary{--bs-link-underline-opacity:1;-webkit-text-decoration-color:rgba(var(--bs-primary-rgb),var(--bs-link-underline-opacity))!important;text-decoration-color:rgba(var(--bs-primary-rgb),var(--bs-link-underline-opacity))!important}.link-underline-secondary{--bs-link-underline-opacity:1;-webkit-text-decoration-color:rgba(var(--bs-secondary-rgb),var(--bs-link-underline-opacity))!important;text-decoration-color:rgba(var(--bs-secondary-rgb),var(--bs-link-underline-opacity))!important}.link-underline-success{--bs-link-underline-opacity:1;-webkit-text-decoration-color:rgba(var(--bs-success-rgb),var(--bs-link-underline-opacity))!important;text-decoration-color:rgba(var(--bs-success-rgb),var(--bs-link-underline-opacity))!important}.link-underline-info{--bs-link-underline-opacity:1;-webkit-text-decoration-color:rgba(var(--bs-info-rgb),var(--bs-link-underline-opacity))!important;text-decoration-color:rgba(var(--bs-info-rgb),var(--bs-link-underline-opacity))!important}.link-underline-warning{--bs-link-underline-opacity:1;-webkit-text-decoration-color:rgba(var(--bs-warning-rgb),var(--bs-link-underline-opacity))!important;text-decoration-color:rgba(var(--bs-warning-rgb),var(--bs-link-underline-opacity))!important}.link-underline-danger{--bs-link-underline-opacity:1;-webkit-text-decoration-color:rgba(var(--bs-danger-rgb),var(--bs-link-underline-opacity))!important;text-decoration-color:rgba(var(--bs-danger-rgb),var(--bs-link-underline-opacity))!important}.link-underline-light{--bs-link-underline-opacity:1;-webkit-text-decoration-color:rgba(var(--bs-light-rgb),var(--bs-link-underline-opacity))!important;text-decoration-color:rgba(var(--bs-light-rgb),var(--bs-link-underline-opacity))!important}.link-underline-dark{--bs-link-underline-opacity:1;-webkit-text-decoration-color:rgba(var(--bs-dark-rgb),var(--bs-link-underline-opacity))!important;text-decoration-color:rgba(var(--bs-dark-rgb),var(--bs-link-underline-opacity))!important}.link-underline{--bs-link-underline-opacity:1;-webkit-text-decoration-color:rgba(var(--bs-link-color-rgb),var(--bs-link-underline-opacity,1))!important;text-decoration-color:rgba(var(--bs-link-color-rgb),var(--bs-link-underline-opacity,1))!important}.link-underline-opacity-0{--bs-link-underline-opacity:0}.link-underline-opacity-0-hover:hover{--bs-link-underline-opacity:0}.link-underline-opacity-10{--bs-link-underline-opacity:0.1}.link-underline-opacity-10-hover:hover{--bs-link-underline-opacity:0.1}.link-underline-opacity-25{--bs-link-underline-opacity:0.25}.link-underline-opacity-25-hover:hover{--bs-link-underline-opacity:0.25}.link-underline-opacity-50{--bs-link-underline-opacity:0.5}.link-underline-opacity-50-hover:hover{--bs-link-underline-opacity:0.5}.link-underline-opacity-75{--bs-link-underline-opacity:0.75}.link-underline-opacity-75-hover:hover{--bs-link-underline-opacity:0.75}.link-underline-opacity-100{--bs-link-underline-opacity:1}.link-underline-opacity-100-hover:hover{--bs-link-underline-opacity:1}.bg-primary{--bs-bg-opacity:1;background-color:rgba(var(--bs-primary-rgb),var(--bs-bg-opacity))!important}.bg-secondary{--bs-bg-opacity:1;background-color:rgba(var(--bs-secondary-rgb),var(--bs-bg-opacity))!important}.bg-success{--bs-bg-opacity:1;background-color:rgba(var(--bs-success-rgb),var(--bs-bg-opacity))!important}.bg-info{--bs-bg-opacity:1;background-color:rgba(var(--bs-info-rgb),var(--bs-bg-opacity))!important}.bg-warning{--bs-bg-opacity:1;background-color:rgba(var(--bs-warning-rgb),var(--bs-bg-opacity))!important}.bg-danger{--bs-bg-opacity:1;background-color:rgba(var(--bs-danger-rgb),var(--bs-bg-opacity))!important}.bg-light{--bs-bg-opacity:1;background-color:rgba(var(--bs-light-rgb),var(--bs-bg-opacity))!important}.bg-dark{--bs-bg-opacity:1;background-color:rgba(var(--bs-dark-rgb),var(--bs-bg-opacity))!important}.bg-black{--bs-bg-opacity:1;background-color:rgba(var(--bs-black-rgb),var(--bs-bg-opacity))!important}.bg-white{--bs-bg-opacity:1;background-color:rgba(var(--bs-white-rgb),var(--bs-bg-opacity))!important}.bg-body{--bs-bg-opacity:1;background-color:rgba(var(--bs-body-bg-rgb),var(--bs-bg-opacity))!important}.bg-transparent{--bs-bg-opacity:1;background-color:transparent!important}.bg-body-secondary{--bs-bg-opacity:1;background-color:rgba(var(--bs-secondary-bg-rgb),var(--bs-bg-opacity))!important}.bg-body-tertiary{--bs-bg-opacity:1;background-color:rgba(var(--bs-tertiary-bg-rgb),var(--bs-bg-opacity))!important}.bg-opacity-10{--bs-bg-opacity:0.1}.bg-opacity-25{--bs-bg-opacity:0.25}.bg-opacity-50{--bs-bg-opacity:0.5}.bg-opacity-75{--bs-bg-opacity:0.75}.bg-opacity-100{--bs-bg-opacity:1}.bg-primary-subtle{background-color:var(--bs-primary-bg-subtle)!important}.bg-secondary-subtle{background-color:var(--bs-secondary-bg-subtle)!important}.bg-success-subtle{background-color:var(--bs-success-bg-subtle)!important}.bg-info-subtle{background-color:var(--bs-info-bg-subtle)!important}.bg-warning-subtle{background-color:var(--bs-warning-bg-subtle)!important}.bg-danger-subtle{background-color:var(--bs-danger-bg-subtle)!important}.bg-light-subtle{background-color:var(--bs-light-bg-subtle)!important}.bg-dark-subtle{background-color:var(--bs-dark-bg-subtle)!important}.bg-gradient{background-image:var(--bs-gradient)!important}.user-select-all{-webkit-user-select:all!important;-moz-user-select:all!important;user-select:all!important}.user-select-auto{-webkit-user-select:auto!important;-moz-user-select:auto!important;user-select:auto!important}.user-select-none{-webkit-user-select:none!important;-moz-user-select:none!important;user-select:none!important}.pe-none{pointer-events:none!important}.pe-auto{pointer-events:auto!important}.rounded{border-radius:var(--bs-border-radius)!important}.rounded-0{border-radius:0!important}.rounded-1{border-radius:var(--bs-border-radius-sm)!important}.rounded-2{border-radius:var(--bs-border-radius)!important}.rounded-3{border-radius:var(--bs-border-radius-lg)!important}.rounded-4{border-radius:var(--bs-border-radius-xl)!important}.rounded-5{border-radius:var(--bs-border-radius-xxl)!important}.rounded-circle{border-radius:50%!important}.rounded-pill{border-radius:var(--bs-border-radius-pill)!important}.rounded-top{border-top-left-radius:var(--bs-border-radius)!important;border-top-right-radius:var(--bs-border-radius)!important}.rounded-top-0{border-top-left-radius:0!important;border-top-right-radius:0!important}.rounded-top-1{border-top-left-radius:var(--bs-border-radius-sm)!important;border-top-right-radius:var(--bs-border-radius-sm)!important}.rounded-top-2{border-top-left-radius:var(--bs-border-radius)!important;border-top-right-radius:var(--bs-border-radius)!important}.rounded-top-3{border-top-left-radius:var(--bs-border-radius-lg)!important;border-top-right-radius:var(--bs-border-radius-lg)!important}.rounded-top-4{border-top-left-radius:var(--bs-border-radius-xl)!important;border-top-right-radius:var(--bs-border-radius-xl)!important}.rounded-top-5{border-top-left-radius:var(--bs-border-radius-xxl)!important;border-top-right-radius:var(--bs-border-radius-xxl)!important}.rounded-top-circle{border-top-left-radius:50%!important;border-top-right-radius:50%!important}.rounded-top-pill{border-top-left-radius:var(--bs-border-radius-pill)!important;border-top-right-radius:var(--bs-border-radius-pill)!important}.rounded-end{border-top-right-radius:var(--bs-border-radius)!important;border-bottom-right-radius:var(--bs-border-radius)!important}.rounded-end-0{border-top-right-radius:0!important;border-bottom-right-radius:0!important}.rounded-end-1{border-top-right-radius:var(--bs-border-radius-sm)!important;border-bottom-right-radius:var(--bs-border-radius-sm)!important}.rounded-end-2{border-top-right-radius:var(--bs-border-radius)!important;border-bottom-right-radius:var(--bs-border-radius)!important}.rounded-end-3{border-top-right-radius:var(--bs-border-radius-lg)!important;border-bottom-right-radius:var(--bs-border-radius-lg)!important}.rounded-end-4{border-top-right-radius:var(--bs-border-radius-xl)!important;border-bottom-right-radius:var(--bs-border-radius-xl)!important}.rounded-end-5{border-top-right-radius:var(--bs-border-radius-xxl)!important;border-bottom-right-radius:var(--bs-border-radius-xxl)!important}.rounded-end-circle{border-top-right-radius:50%!important;border-bottom-right-radius:50%!important}.rounded-end-pill{border-top-right-radius:var(--bs-border-radius-pill)!important;border-bottom-right-radius:var(--bs-border-radius-pill)!important}.rounded-bottom{border-bottom-right-radius:var(--bs-border-radius)!important;border-bottom-left-radius:var(--bs-border-radius)!important}.rounded-bottom-0{border-bottom-right-radius:0!important;border-bottom-left-radius:0!important}.rounded-bottom-1{border-bottom-right-radius:var(--bs-border-radius-sm)!important;border-bottom-left-radius:var(--bs-border-radius-sm)!important}.rounded-bottom-2{border-bottom-right-radius:var(--bs-border-radius)!important;border-bottom-left-radius:var(--bs-border-radius)!important}.rounded-bottom-3{border-bottom-right-radius:var(--bs-border-radius-lg)!important;border-bottom-left-radius:var(--bs-border-radius-lg)!important}.rounded-bottom-4{border-bottom-right-radius:var(--bs-border-radius-xl)!important;border-bottom-left-radius:var(--bs-border-radius-xl)!important}.rounded-bottom-5{border-bottom-right-radius:var(--bs-border-radius-xxl)!important;border-bottom-left-radius:var(--bs-border-radius-xxl)!important}.rounded-bottom-circle{border-bottom-right-radius:50%!important;border-bottom-left-radius:50%!important}.rounded-bottom-pill{border-bottom-right-radius:var(--bs-border-radius-pill)!important;border-bottom-left-radius:var(--bs-border-radius-pill)!important}.rounded-start{border-bottom-left-radius:var(--bs-border-radius)!important;border-top-left-radius:var(--bs-border-radius)!important}.rounded-start-0{border-bottom-left-radius:0!important;border-top-left-radius:0!important}.rounded-start-1{border-bottom-left-radius:var(--bs-border-radius-sm)!important;border-top-left-radius:var(--bs-border-radius-sm)!important}.rounded-start-2{border-bottom-left-radius:var(--bs-border-radius)!important;border-top-left-radius:var(--bs-border-radius)!important}.rounded-start-3{border-bottom-left-radius:var(--bs-border-radius-lg)!important;border-top-left-radius:var(--bs-border-radius-lg)!important}.rounded-start-4{border-bottom-left-radius:var(--bs-border-radius-xl)!important;border-top-left-radius:var(--bs-border-radius-xl)!important}.rounded-start-5{border-bottom-left-radius:var(--bs-border-radius-xxl)!important;border-top-left-radius:var(--bs-border-radius-xxl)!important}.rounded-start-circle{border-bottom-left-radius:50%!important;border-top-left-radius:50%!important}.rounded-start-pill{border-bottom-left-radius:var(--bs-border-radius-pill)!important;border-top-left-radius:var(--bs-border-radius-pill)!important}.visible{visibility:visible!important}.invisible{visibility:hidden!important}.z-n1{z-index:-1!important}.z-0{z-index:0!important}.z-1{z-index:1!important}.z-2{z-index:2!important}.z-3{z-index:3!important}@media (min-width:576px){.float-sm-start{float:left!important}.float-sm-end{float:right!important}.float-sm-none{float:none!important}.object-fit-sm-contain{-o-object-fit:contain!important;object-fit:contain!important}.object-fit-sm-cover{-o-object-fit:cover!important;object-fit:cover!important}.object-fit-sm-fill{-o-object-fit:fill!important;object-fit:fill!important}.object-fit-sm-scale{-o-object-fit:scale-down!important;object-fit:scale-down!important}.object-fit-sm-none{-o-object-fit:none!important;object-fit:none!important}.d-sm-inline{display:inline!important}.d-sm-inline-block{display:inline-block!important}.d-sm-block{display:block!important}.d-sm-grid{display:grid!important}.d-sm-inline-grid{display:inline-grid!important}.d-sm-table{display:table!important}.d-sm-table-row{display:table-row!important}.d-sm-table-cell{display:table-cell!important}.d-sm-flex{display:flex!important}.d-sm-inline-flex{display:inline-flex!important}.d-sm-none{display:none!important}.flex-sm-fill{flex:1 1 auto!important}.flex-sm-row{flex-direction:row!important}.flex-sm-column{flex-direction:column!important}.flex-sm-row-reverse{flex-direction:row-reverse!important}.flex-sm-column-reverse{flex-direction:column-reverse!important}.flex-sm-grow-0{flex-grow:0!important}.flex-sm-grow-1{flex-grow:1!important}.flex-sm-shrink-0{flex-shrink:0!important}.flex-sm-shrink-1{flex-shrink:1!important}.flex-sm-wrap{flex-wrap:wrap!important}.flex-sm-nowrap{flex-wrap:nowrap!important}.flex-sm-wrap-reverse{flex-wrap:wrap-reverse!important}.justify-content-sm-start{justify-content:flex-start!important}.justify-content-sm-end{justify-content:flex-end!important}.justify-content-sm-center{justify-content:center!important}.justify-content-sm-between{justify-content:space-between!important}.justify-content-sm-around{justify-content:space-around!important}.justify-content-sm-evenly{justify-content:space-evenly!important}.align-items-sm-start{align-items:flex-start!important}.align-items-sm-end{align-items:flex-end!important}.align-items-sm-center{align-items:center!important}.align-items-sm-baseline{align-items:baseline!important}.align-items-sm-stretch{align-items:stretch!important}.align-content-sm-start{align-content:flex-start!important}.align-content-sm-end{align-content:flex-end!important}.align-content-sm-center{align-content:center!important}.align-content-sm-between{align-content:space-between!important}.align-content-sm-around{align-content:space-around!important}.align-content-sm-stretch{align-content:stretch!important}.align-self-sm-auto{align-self:auto!important}.align-self-sm-start{align-self:flex-start!important}.align-self-sm-end{align-self:flex-end!important}.align-self-sm-center{align-self:center!important}.align-self-sm-baseline{align-self:baseline!important}.align-self-sm-stretch{align-self:stretch!important}.order-sm-first{order:-1!important}.order-sm-0{order:0!important}.order-sm-1{order:1!important}.order-sm-2{order:2!important}.order-sm-3{order:3!important}.order-sm-4{order:4!important}.order-sm-5{order:5!important}.order-sm-last{order:6!important}.m-sm-0{margin:0!important}.m-sm-1{margin:.25rem!important}.m-sm-2{margin:.5rem!important}.m-sm-3{margin:1rem!important}.m-sm-4{margin:1.5rem!important}.m-sm-5{margin:3rem!important}.m-sm-auto{margin:auto!important}.mx-sm-0{margin-right:0!important;margin-left:0!important}.mx-sm-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-sm-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-sm-3{margin-right:1rem!important;margin-left:1rem!important}.mx-sm-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-sm-5{margin-right:3rem!important;margin-left:3rem!important}.mx-sm-auto{margin-right:auto!important;margin-left:auto!important}.my-sm-0{margin-top:0!important;margin-bottom:0!important}.my-sm-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-sm-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-sm-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-sm-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-sm-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-sm-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-sm-0{margin-top:0!important}.mt-sm-1{margin-top:.25rem!important}.mt-sm-2{margin-top:.5rem!important}.mt-sm-3{margin-top:1rem!important}.mt-sm-4{margin-top:1.5rem!important}.mt-sm-5{margin-top:3rem!important}.mt-sm-auto{margin-top:auto!important}.me-sm-0{margin-right:0!important}.me-sm-1{margin-right:.25rem!important}.me-sm-2{margin-right:.5rem!important}.me-sm-3{margin-right:1rem!important}.me-sm-4{margin-right:1.5rem!important}.me-sm-5{margin-right:3rem!important}.me-sm-auto{margin-right:auto!important}.mb-sm-0{margin-bottom:0!important}.mb-sm-1{margin-bottom:.25rem!important}.mb-sm-2{margin-bottom:.5rem!important}.mb-sm-3{margin-bottom:1rem!important}.mb-sm-4{margin-bottom:1.5rem!important}.mb-sm-5{margin-bottom:3rem!important}.mb-sm-auto{margin-bottom:auto!important}.ms-sm-0{margin-left:0!important}.ms-sm-1{margin-left:.25rem!important}.ms-sm-2{margin-left:.5rem!important}.ms-sm-3{margin-left:1rem!important}.ms-sm-4{margin-left:1.5rem!important}.ms-sm-5{margin-left:3rem!important}.ms-sm-auto{margin-left:auto!important}.p-sm-0{padding:0!important}.p-sm-1{padding:.25rem!important}.p-sm-2{padding:.5rem!important}.p-sm-3{padding:1rem!important}.p-sm-4{padding:1.5rem!important}.p-sm-5{padding:3rem!important}.px-sm-0{padding-right:0!important;padding-left:0!important}.px-sm-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-sm-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-sm-3{padding-right:1rem!important;padding-left:1rem!important}.px-sm-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-sm-5{padding-right:3rem!important;padding-left:3rem!important}.py-sm-0{padding-top:0!important;padding-bottom:0!important}.py-sm-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-sm-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-sm-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-sm-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-sm-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-sm-0{padding-top:0!important}.pt-sm-1{padding-top:.25rem!important}.pt-sm-2{padding-top:.5rem!important}.pt-sm-3{padding-top:1rem!important}.pt-sm-4{padding-top:1.5rem!important}.pt-sm-5{padding-top:3rem!important}.pe-sm-0{padding-right:0!important}.pe-sm-1{padding-right:.25rem!important}.pe-sm-2{padding-right:.5rem!important}.pe-sm-3{padding-right:1rem!important}.pe-sm-4{padding-right:1.5rem!important}.pe-sm-5{padding-right:3rem!important}.pb-sm-0{padding-bottom:0!important}.pb-sm-1{padding-bottom:.25rem!important}.pb-sm-2{padding-bottom:.5rem!important}.pb-sm-3{padding-bottom:1rem!important}.pb-sm-4{padding-bottom:1.5rem!important}.pb-sm-5{padding-bottom:3rem!important}.ps-sm-0{padding-left:0!important}.ps-sm-1{padding-left:.25rem!important}.ps-sm-2{padding-left:.5rem!important}.ps-sm-3{padding-left:1rem!important}.ps-sm-4{padding-left:1.5rem!important}.ps-sm-5{padding-left:3rem!important}.gap-sm-0{gap:0!important}.gap-sm-1{gap:.25rem!important}.gap-sm-2{gap:.5rem!important}.gap-sm-3{gap:1rem!important}.gap-sm-4{gap:1.5rem!important}.gap-sm-5{gap:3rem!important}.row-gap-sm-0{row-gap:0!important}.row-gap-sm-1{row-gap:.25rem!important}.row-gap-sm-2{row-gap:.5rem!important}.row-gap-sm-3{row-gap:1rem!important}.row-gap-sm-4{row-gap:1.5rem!important}.row-gap-sm-5{row-gap:3rem!important}.column-gap-sm-0{-moz-column-gap:0!important;column-gap:0!important}.column-gap-sm-1{-moz-column-gap:0.25rem!important;column-gap:.25rem!important}.column-gap-sm-2{-moz-column-gap:0.5rem!important;column-gap:.5rem!important}.column-gap-sm-3{-moz-column-gap:1rem!important;column-gap:1rem!important}.column-gap-sm-4{-moz-column-gap:1.5rem!important;column-gap:1.5rem!important}.column-gap-sm-5{-moz-column-gap:3rem!important;column-gap:3rem!important}.text-sm-start{text-align:left!important}.text-sm-end{text-align:right!important}.text-sm-center{text-align:center!important}}@media (min-width:768px){.float-md-start{float:left!important}.float-md-end{float:right!important}.float-md-none{float:none!important}.object-fit-md-contain{-o-object-fit:contain!important;object-fit:contain!important}.object-fit-md-cover{-o-object-fit:cover!important;object-fit:cover!important}.object-fit-md-fill{-o-object-fit:fill!important;object-fit:fill!important}.object-fit-md-scale{-o-object-fit:scale-down!important;object-fit:scale-down!important}.object-fit-md-none{-o-object-fit:none!important;object-fit:none!important}.d-md-inline{display:inline!important}.d-md-inline-block{display:inline-block!important}.d-md-block{display:block!important}.d-md-grid{display:grid!important}.d-md-inline-grid{display:inline-grid!important}.d-md-table{display:table!important}.d-md-table-row{display:table-row!important}.d-md-table-cell{display:table-cell!important}.d-md-flex{display:flex!important}.d-md-inline-flex{display:inline-flex!important}.d-md-none{display:none!important}.flex-md-fill{flex:1 1 auto!important}.flex-md-row{flex-direction:row!important}.flex-md-column{flex-direction:column!important}.flex-md-row-reverse{flex-direction:row-reverse!important}.flex-md-column-reverse{flex-direction:column-reverse!important}.flex-md-grow-0{flex-grow:0!important}.flex-md-grow-1{flex-grow:1!important}.flex-md-shrink-0{flex-shrink:0!important}.flex-md-shrink-1{flex-shrink:1!important}.flex-md-wrap{flex-wrap:wrap!important}.flex-md-nowrap{flex-wrap:nowrap!important}.flex-md-wrap-reverse{flex-wrap:wrap-reverse!important}.justify-content-md-start{justify-content:flex-start!important}.justify-content-md-end{justify-content:flex-end!important}.justify-content-md-center{justify-content:center!important}.justify-content-md-between{justify-content:space-between!important}.justify-content-md-around{justify-content:space-around!important}.justify-content-md-evenly{justify-content:space-evenly!important}.align-items-md-start{align-items:flex-start!important}.align-items-md-end{align-items:flex-end!important}.align-items-md-center{align-items:center!important}.align-items-md-baseline{align-items:baseline!important}.align-items-md-stretch{align-items:stretch!important}.align-content-md-start{align-content:flex-start!important}.align-content-md-end{align-content:flex-end!important}.align-content-md-center{align-content:center!important}.align-content-md-between{align-content:space-between!important}.align-content-md-around{align-content:space-around!important}.align-content-md-stretch{align-content:stretch!important}.align-self-md-auto{align-self:auto!important}.align-self-md-start{align-self:flex-start!important}.align-self-md-end{align-self:flex-end!important}.align-self-md-center{align-self:center!important}.align-self-md-baseline{align-self:baseline!important}.align-self-md-stretch{align-self:stretch!important}.order-md-first{order:-1!important}.order-md-0{order:0!important}.order-md-1{order:1!important}.order-md-2{order:2!important}.order-md-3{order:3!important}.order-md-4{order:4!important}.order-md-5{order:5!important}.order-md-last{order:6!important}.m-md-0{margin:0!important}.m-md-1{margin:.25rem!important}.m-md-2{margin:.5rem!important}.m-md-3{margin:1rem!important}.m-md-4{margin:1.5rem!important}.m-md-5{margin:3rem!important}.m-md-auto{margin:auto!important}.mx-md-0{margin-right:0!important;margin-left:0!important}.mx-md-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-md-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-md-3{margin-right:1rem!important;margin-left:1rem!important}.mx-md-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-md-5{margin-right:3rem!important;margin-left:3rem!important}.mx-md-auto{margin-right:auto!important;margin-left:auto!important}.my-md-0{margin-top:0!important;margin-bottom:0!important}.my-md-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-md-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-md-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-md-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-md-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-md-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-md-0{margin-top:0!important}.mt-md-1{margin-top:.25rem!important}.mt-md-2{margin-top:.5rem!important}.mt-md-3{margin-top:1rem!important}.mt-md-4{margin-top:1.5rem!important}.mt-md-5{margin-top:3rem!important}.mt-md-auto{margin-top:auto!important}.me-md-0{margin-right:0!important}.me-md-1{margin-right:.25rem!important}.me-md-2{margin-right:.5rem!important}.me-md-3{margin-right:1rem!important}.me-md-4{margin-right:1.5rem!important}.me-md-5{margin-right:3rem!important}.me-md-auto{margin-right:auto!important}.mb-md-0{margin-bottom:0!important}.mb-md-1{margin-bottom:.25rem!important}.mb-md-2{margin-bottom:.5rem!important}.mb-md-3{margin-bottom:1rem!important}.mb-md-4{margin-bottom:1.5rem!important}.mb-md-5{margin-bottom:3rem!important}.mb-md-auto{margin-bottom:auto!important}.ms-md-0{margin-left:0!important}.ms-md-1{margin-left:.25rem!important}.ms-md-2{margin-left:.5rem!important}.ms-md-3{margin-left:1rem!important}.ms-md-4{margin-left:1.5rem!important}.ms-md-5{margin-left:3rem!important}.ms-md-auto{margin-left:auto!important}.p-md-0{padding:0!important}.p-md-1{padding:.25rem!important}.p-md-2{padding:.5rem!important}.p-md-3{padding:1rem!important}.p-md-4{padding:1.5rem!important}.p-md-5{padding:3rem!important}.px-md-0{padding-right:0!important;padding-left:0!important}.px-md-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-md-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-md-3{padding-right:1rem!important;padding-left:1rem!important}.px-md-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-md-5{padding-right:3rem!important;padding-left:3rem!important}.py-md-0{padding-top:0!important;padding-bottom:0!important}.py-md-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-md-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-md-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-md-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-md-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-md-0{padding-top:0!important}.pt-md-1{padding-top:.25rem!important}.pt-md-2{padding-top:.5rem!important}.pt-md-3{padding-top:1rem!important}.pt-md-4{padding-top:1.5rem!important}.pt-md-5{padding-top:3rem!important}.pe-md-0{padding-right:0!important}.pe-md-1{padding-right:.25rem!important}.pe-md-2{padding-right:.5rem!important}.pe-md-3{padding-right:1rem!important}.pe-md-4{padding-right:1.5rem!important}.pe-md-5{padding-right:3rem!important}.pb-md-0{padding-bottom:0!important}.pb-md-1{padding-bottom:.25rem!important}.pb-md-2{padding-bottom:.5rem!important}.pb-md-3{padding-bottom:1rem!important}.pb-md-4{padding-bottom:1.5rem!important}.pb-md-5{padding-bottom:3rem!important}.ps-md-0{padding-left:0!important}.ps-md-1{padding-left:.25rem!important}.ps-md-2{padding-left:.5rem!important}.ps-md-3{padding-left:1rem!important}.ps-md-4{padding-left:1.5rem!important}.ps-md-5{padding-left:3rem!important}.gap-md-0{gap:0!important}.gap-md-1{gap:.25rem!important}.gap-md-2{gap:.5rem!important}.gap-md-3{gap:1rem!important}.gap-md-4{gap:1.5rem!important}.gap-md-5{gap:3rem!important}.row-gap-md-0{row-gap:0!important}.row-gap-md-1{row-gap:.25rem!important}.row-gap-md-2{row-gap:.5rem!important}.row-gap-md-3{row-gap:1rem!important}.row-gap-md-4{row-gap:1.5rem!important}.row-gap-md-5{row-gap:3rem!important}.column-gap-md-0{-moz-column-gap:0!important;column-gap:0!important}.column-gap-md-1{-moz-column-gap:0.25rem!important;column-gap:.25rem!important}.column-gap-md-2{-moz-column-gap:0.5rem!important;column-gap:.5rem!important}.column-gap-md-3{-moz-column-gap:1rem!important;column-gap:1rem!important}.column-gap-md-4{-moz-column-gap:1.5rem!important;column-gap:1.5rem!important}.column-gap-md-5{-moz-column-gap:3rem!important;column-gap:3rem!important}.text-md-start{text-align:left!important}.text-md-end{text-align:right!important}.text-md-center{text-align:center!important}}@media (min-width:992px){.float-lg-start{float:left!important}.float-lg-end{float:right!important}.float-lg-none{float:none!important}.object-fit-lg-contain{-o-object-fit:contain!important;object-fit:contain!important}.object-fit-lg-cover{-o-object-fit:cover!important;object-fit:cover!important}.object-fit-lg-fill{-o-object-fit:fill!important;object-fit:fill!important}.object-fit-lg-scale{-o-object-fit:scale-down!important;object-fit:scale-down!important}.object-fit-lg-none{-o-object-fit:none!important;object-fit:none!important}.d-lg-inline{display:inline!important}.d-lg-inline-block{display:inline-block!important}.d-lg-block{display:block!important}.d-lg-grid{display:grid!important}.d-lg-inline-grid{display:inline-grid!important}.d-lg-table{display:table!important}.d-lg-table-row{display:table-row!important}.d-lg-table-cell{display:table-cell!important}.d-lg-flex{display:flex!important}.d-lg-inline-flex{display:inline-flex!important}.d-lg-none{display:none!important}.flex-lg-fill{flex:1 1 auto!important}.flex-lg-row{flex-direction:row!important}.flex-lg-column{flex-direction:column!important}.flex-lg-row-reverse{flex-direction:row-reverse!important}.flex-lg-column-reverse{flex-direction:column-reverse!important}.flex-lg-grow-0{flex-grow:0!important}.flex-lg-grow-1{flex-grow:1!important}.flex-lg-shrink-0{flex-shrink:0!important}.flex-lg-shrink-1{flex-shrink:1!important}.flex-lg-wrap{flex-wrap:wrap!important}.flex-lg-nowrap{flex-wrap:nowrap!important}.flex-lg-wrap-reverse{flex-wrap:wrap-reverse!important}.justify-content-lg-start{justify-content:flex-start!important}.justify-content-lg-end{justify-content:flex-end!important}.justify-content-lg-center{justify-content:center!important}.justify-content-lg-between{justify-content:space-between!important}.justify-content-lg-around{justify-content:space-around!important}.justify-content-lg-evenly{justify-content:space-evenly!important}.align-items-lg-start{align-items:flex-start!important}.align-items-lg-end{align-items:flex-end!important}.align-items-lg-center{align-items:center!important}.align-items-lg-baseline{align-items:baseline!important}.align-items-lg-stretch{align-items:stretch!important}.align-content-lg-start{align-content:flex-start!important}.align-content-lg-end{align-content:flex-end!important}.align-content-lg-center{align-content:center!important}.align-content-lg-between{align-content:space-between!important}.align-content-lg-around{align-content:space-around!important}.align-content-lg-stretch{align-content:stretch!important}.align-self-lg-auto{align-self:auto!important}.align-self-lg-start{align-self:flex-start!important}.align-self-lg-end{align-self:flex-end!important}.align-self-lg-center{align-self:center!important}.align-self-lg-baseline{align-self:baseline!important}.align-self-lg-stretch{align-self:stretch!important}.order-lg-first{order:-1!important}.order-lg-0{order:0!important}.order-lg-1{order:1!important}.order-lg-2{order:2!important}.order-lg-3{order:3!important}.order-lg-4{order:4!important}.order-lg-5{order:5!important}.order-lg-last{order:6!important}.m-lg-0{margin:0!important}.m-lg-1{margin:.25rem!important}.m-lg-2{margin:.5rem!important}.m-lg-3{margin:1rem!important}.m-lg-4{margin:1.5rem!important}.m-lg-5{margin:3rem!important}.m-lg-auto{margin:auto!important}.mx-lg-0{margin-right:0!important;margin-left:0!important}.mx-lg-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-lg-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-lg-3{margin-right:1rem!important;margin-left:1rem!important}.mx-lg-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-lg-5{margin-right:3rem!important;margin-left:3rem!important}.mx-lg-auto{margin-right:auto!important;margin-left:auto!important}.my-lg-0{margin-top:0!important;margin-bottom:0!important}.my-lg-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-lg-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-lg-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-lg-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-lg-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-lg-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-lg-0{margin-top:0!important}.mt-lg-1{margin-top:.25rem!important}.mt-lg-2{margin-top:.5rem!important}.mt-lg-3{margin-top:1rem!important}.mt-lg-4{margin-top:1.5rem!important}.mt-lg-5{margin-top:3rem!important}.mt-lg-auto{margin-top:auto!important}.me-lg-0{margin-right:0!important}.me-lg-1{margin-right:.25rem!important}.me-lg-2{margin-right:.5rem!important}.me-lg-3{margin-right:1rem!important}.me-lg-4{margin-right:1.5rem!important}.me-lg-5{margin-right:3rem!important}.me-lg-auto{margin-right:auto!important}.mb-lg-0{margin-bottom:0!important}.mb-lg-1{margin-bottom:.25rem!important}.mb-lg-2{margin-bottom:.5rem!important}.mb-lg-3{margin-bottom:1rem!important}.mb-lg-4{margin-bottom:1.5rem!important}.mb-lg-5{margin-bottom:3rem!important}.mb-lg-auto{margin-bottom:auto!important}.ms-lg-0{margin-left:0!important}.ms-lg-1{margin-left:.25rem!important}.ms-lg-2{margin-left:.5rem!important}.ms-lg-3{margin-left:1rem!important}.ms-lg-4{margin-left:1.5rem!important}.ms-lg-5{margin-left:3rem!important}.ms-lg-auto{margin-left:auto!important}.p-lg-0{padding:0!important}.p-lg-1{padding:.25rem!important}.p-lg-2{padding:.5rem!important}.p-lg-3{padding:1rem!important}.p-lg-4{padding:1.5rem!important}.p-lg-5{padding:3rem!important}.px-lg-0{padding-right:0!important;padding-left:0!important}.px-lg-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-lg-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-lg-3{padding-right:1rem!important;padding-left:1rem!important}.px-lg-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-lg-5{padding-right:3rem!important;padding-left:3rem!important}.py-lg-0{padding-top:0!important;padding-bottom:0!important}.py-lg-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-lg-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-lg-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-lg-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-lg-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-lg-0{padding-top:0!important}.pt-lg-1{padding-top:.25rem!important}.pt-lg-2{padding-top:.5rem!important}.pt-lg-3{padding-top:1rem!important}.pt-lg-4{padding-top:1.5rem!important}.pt-lg-5{padding-top:3rem!important}.pe-lg-0{padding-right:0!important}.pe-lg-1{padding-right:.25rem!important}.pe-lg-2{padding-right:.5rem!important}.pe-lg-3{padding-right:1rem!important}.pe-lg-4{padding-right:1.5rem!important}.pe-lg-5{padding-right:3rem!important}.pb-lg-0{padding-bottom:0!important}.pb-lg-1{padding-bottom:.25rem!important}.pb-lg-2{padding-bottom:.5rem!important}.pb-lg-3{padding-bottom:1rem!important}.pb-lg-4{padding-bottom:1.5rem!important}.pb-lg-5{padding-bottom:3rem!important}.ps-lg-0{padding-left:0!important}.ps-lg-1{padding-left:.25rem!important}.ps-lg-2{padding-left:.5rem!important}.ps-lg-3{padding-left:1rem!important}.ps-lg-4{padding-left:1.5rem!important}.ps-lg-5{padding-left:3rem!important}.gap-lg-0{gap:0!important}.gap-lg-1{gap:.25rem!important}.gap-lg-2{gap:.5rem!important}.gap-lg-3{gap:1rem!important}.gap-lg-4{gap:1.5rem!important}.gap-lg-5{gap:3rem!important}.row-gap-lg-0{row-gap:0!important}.row-gap-lg-1{row-gap:.25rem!important}.row-gap-lg-2{row-gap:.5rem!important}.row-gap-lg-3{row-gap:1rem!important}.row-gap-lg-4{row-gap:1.5rem!important}.row-gap-lg-5{row-gap:3rem!important}.column-gap-lg-0{-moz-column-gap:0!important;column-gap:0!important}.column-gap-lg-1{-moz-column-gap:0.25rem!important;column-gap:.25rem!important}.column-gap-lg-2{-moz-column-gap:0.5rem!important;column-gap:.5rem!important}.column-gap-lg-3{-moz-column-gap:1rem!important;column-gap:1rem!important}.column-gap-lg-4{-moz-column-gap:1.5rem!important;column-gap:1.5rem!important}.column-gap-lg-5{-moz-column-gap:3rem!important;column-gap:3rem!important}.text-lg-start{text-align:left!important}.text-lg-end{text-align:right!important}.text-lg-center{text-align:center!important}}@media (min-width:1200px){.float-xl-start{float:left!important}.float-xl-end{float:right!important}.float-xl-none{float:none!important}.object-fit-xl-contain{-o-object-fit:contain!important;object-fit:contain!important}.object-fit-xl-cover{-o-object-fit:cover!important;object-fit:cover!important}.object-fit-xl-fill{-o-object-fit:fill!important;object-fit:fill!important}.object-fit-xl-scale{-o-object-fit:scale-down!important;object-fit:scale-down!important}.object-fit-xl-none{-o-object-fit:none!important;object-fit:none!important}.d-xl-inline{display:inline!important}.d-xl-inline-block{display:inline-block!important}.d-xl-block{display:block!important}.d-xl-grid{display:grid!important}.d-xl-inline-grid{display:inline-grid!important}.d-xl-table{display:table!important}.d-xl-table-row{display:table-row!important}.d-xl-table-cell{display:table-cell!important}.d-xl-flex{display:flex!important}.d-xl-inline-flex{display:inline-flex!important}.d-xl-none{display:none!important}.flex-xl-fill{flex:1 1 auto!important}.flex-xl-row{flex-direction:row!important}.flex-xl-column{flex-direction:column!important}.flex-xl-row-reverse{flex-direction:row-reverse!important}.flex-xl-column-reverse{flex-direction:column-reverse!important}.flex-xl-grow-0{flex-grow:0!important}.flex-xl-grow-1{flex-grow:1!important}.flex-xl-shrink-0{flex-shrink:0!important}.flex-xl-shrink-1{flex-shrink:1!important}.flex-xl-wrap{flex-wrap:wrap!important}.flex-xl-nowrap{flex-wrap:nowrap!important}.flex-xl-wrap-reverse{flex-wrap:wrap-reverse!important}.justify-content-xl-start{justify-content:flex-start!important}.justify-content-xl-end{justify-content:flex-end!important}.justify-content-xl-center{justify-content:center!important}.justify-content-xl-between{justify-content:space-between!important}.justify-content-xl-around{justify-content:space-around!important}.justify-content-xl-evenly{justify-content:space-evenly!important}.align-items-xl-start{align-items:flex-start!important}.align-items-xl-end{align-items:flex-end!important}.align-items-xl-center{align-items:center!important}.align-items-xl-baseline{align-items:baseline!important}.align-items-xl-stretch{align-items:stretch!important}.align-content-xl-start{align-content:flex-start!important}.align-content-xl-end{align-content:flex-end!important}.align-content-xl-center{align-content:center!important}.align-content-xl-between{align-content:space-between!important}.align-content-xl-around{align-content:space-around!important}.align-content-xl-stretch{align-content:stretch!important}.align-self-xl-auto{align-self:auto!important}.align-self-xl-start{align-self:flex-start!important}.align-self-xl-end{align-self:flex-end!important}.align-self-xl-center{align-self:center!important}.align-self-xl-baseline{align-self:baseline!important}.align-self-xl-stretch{align-self:stretch!important}.order-xl-first{order:-1!important}.order-xl-0{order:0!important}.order-xl-1{order:1!important}.order-xl-2{order:2!important}.order-xl-3{order:3!important}.order-xl-4{order:4!important}.order-xl-5{order:5!important}.order-xl-last{order:6!important}.m-xl-0{margin:0!important}.m-xl-1{margin:.25rem!important}.m-xl-2{margin:.5rem!important}.m-xl-3{margin:1rem!important}.m-xl-4{margin:1.5rem!important}.m-xl-5{margin:3rem!important}.m-xl-auto{margin:auto!important}.mx-xl-0{margin-right:0!important;margin-left:0!important}.mx-xl-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-xl-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-xl-3{margin-right:1rem!important;margin-left:1rem!important}.mx-xl-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-xl-5{margin-right:3rem!important;margin-left:3rem!important}.mx-xl-auto{margin-right:auto!important;margin-left:auto!important}.my-xl-0{margin-top:0!important;margin-bottom:0!important}.my-xl-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-xl-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-xl-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-xl-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-xl-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-xl-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-xl-0{margin-top:0!important}.mt-xl-1{margin-top:.25rem!important}.mt-xl-2{margin-top:.5rem!important}.mt-xl-3{margin-top:1rem!important}.mt-xl-4{margin-top:1.5rem!important}.mt-xl-5{margin-top:3rem!important}.mt-xl-auto{margin-top:auto!important}.me-xl-0{margin-right:0!important}.me-xl-1{margin-right:.25rem!important}.me-xl-2{margin-right:.5rem!important}.me-xl-3{margin-right:1rem!important}.me-xl-4{margin-right:1.5rem!important}.me-xl-5{margin-right:3rem!important}.me-xl-auto{margin-right:auto!important}.mb-xl-0{margin-bottom:0!important}.mb-xl-1{margin-bottom:.25rem!important}.mb-xl-2{margin-bottom:.5rem!important}.mb-xl-3{margin-bottom:1rem!important}.mb-xl-4{margin-bottom:1.5rem!important}.mb-xl-5{margin-bottom:3rem!important}.mb-xl-auto{margin-bottom:auto!important}.ms-xl-0{margin-left:0!important}.ms-xl-1{margin-left:.25rem!important}.ms-xl-2{margin-left:.5rem!important}.ms-xl-3{margin-left:1rem!important}.ms-xl-4{margin-left:1.5rem!important}.ms-xl-5{margin-left:3rem!important}.ms-xl-auto{margin-left:auto!important}.p-xl-0{padding:0!important}.p-xl-1{padding:.25rem!important}.p-xl-2{padding:.5rem!important}.p-xl-3{padding:1rem!important}.p-xl-4{padding:1.5rem!important}.p-xl-5{padding:3rem!important}.px-xl-0{padding-right:0!important;padding-left:0!important}.px-xl-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-xl-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-xl-3{padding-right:1rem!important;padding-left:1rem!important}.px-xl-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-xl-5{padding-right:3rem!important;padding-left:3rem!important}.py-xl-0{padding-top:0!important;padding-bottom:0!important}.py-xl-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-xl-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-xl-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-xl-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-xl-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-xl-0{padding-top:0!important}.pt-xl-1{padding-top:.25rem!important}.pt-xl-2{padding-top:.5rem!important}.pt-xl-3{padding-top:1rem!important}.pt-xl-4{padding-top:1.5rem!important}.pt-xl-5{padding-top:3rem!important}.pe-xl-0{padding-right:0!important}.pe-xl-1{padding-right:.25rem!important}.pe-xl-2{padding-right:.5rem!important}.pe-xl-3{padding-right:1rem!important}.pe-xl-4{padding-right:1.5rem!important}.pe-xl-5{padding-right:3rem!important}.pb-xl-0{padding-bottom:0!important}.pb-xl-1{padding-bottom:.25rem!important}.pb-xl-2{padding-bottom:.5rem!important}.pb-xl-3{padding-bottom:1rem!important}.pb-xl-4{padding-bottom:1.5rem!important}.pb-xl-5{padding-bottom:3rem!important}.ps-xl-0{padding-left:0!important}.ps-xl-1{padding-left:.25rem!important}.ps-xl-2{padding-left:.5rem!important}.ps-xl-3{padding-left:1rem!important}.ps-xl-4{padding-left:1.5rem!important}.ps-xl-5{padding-left:3rem!important}.gap-xl-0{gap:0!important}.gap-xl-1{gap:.25rem!important}.gap-xl-2{gap:.5rem!important}.gap-xl-3{gap:1rem!important}.gap-xl-4{gap:1.5rem!important}.gap-xl-5{gap:3rem!important}.row-gap-xl-0{row-gap:0!important}.row-gap-xl-1{row-gap:.25rem!important}.row-gap-xl-2{row-gap:.5rem!important}.row-gap-xl-3{row-gap:1rem!important}.row-gap-xl-4{row-gap:1.5rem!important}.row-gap-xl-5{row-gap:3rem!important}.column-gap-xl-0{-moz-column-gap:0!important;column-gap:0!important}.column-gap-xl-1{-moz-column-gap:0.25rem!important;column-gap:.25rem!important}.column-gap-xl-2{-moz-column-gap:0.5rem!important;column-gap:.5rem!important}.column-gap-xl-3{-moz-column-gap:1rem!important;column-gap:1rem!important}.column-gap-xl-4{-moz-column-gap:1.5rem!important;column-gap:1.5rem!important}.column-gap-xl-5{-moz-column-gap:3rem!important;column-gap:3rem!important}.text-xl-start{text-align:left!important}.text-xl-end{text-align:right!important}.text-xl-center{text-align:center!important}}@media (min-width:1400px){.float-xxl-start{float:left!important}.float-xxl-end{float:right!important}.float-xxl-none{float:none!important}.object-fit-xxl-contain{-o-object-fit:contain!important;object-fit:contain!important}.object-fit-xxl-cover{-o-object-fit:cover!important;object-fit:cover!important}.object-fit-xxl-fill{-o-object-fit:fill!important;object-fit:fill!important}.object-fit-xxl-scale{-o-object-fit:scale-down!important;object-fit:scale-down!important}.object-fit-xxl-none{-o-object-fit:none!important;object-fit:none!important}.d-xxl-inline{display:inline!important}.d-xxl-inline-block{display:inline-block!important}.d-xxl-block{display:block!important}.d-xxl-grid{display:grid!important}.d-xxl-inline-grid{display:inline-grid!important}.d-xxl-table{display:table!important}.d-xxl-table-row{display:table-row!important}.d-xxl-table-cell{display:table-cell!important}.d-xxl-flex{display:flex!important}.d-xxl-inline-flex{display:inline-flex!important}.d-xxl-none{display:none!important}.flex-xxl-fill{flex:1 1 auto!important}.flex-xxl-row{flex-direction:row!important}.flex-xxl-column{flex-direction:column!important}.flex-xxl-row-reverse{flex-direction:row-reverse!important}.flex-xxl-column-reverse{flex-direction:column-reverse!important}.flex-xxl-grow-0{flex-grow:0!important}.flex-xxl-grow-1{flex-grow:1!important}.flex-xxl-shrink-0{flex-shrink:0!important}.flex-xxl-shrink-1{flex-shrink:1!important}.flex-xxl-wrap{flex-wrap:wrap!important}.flex-xxl-nowrap{flex-wrap:nowrap!important}.flex-xxl-wrap-reverse{flex-wrap:wrap-reverse!important}.justify-content-xxl-start{justify-content:flex-start!important}.justify-content-xxl-end{justify-content:flex-end!important}.justify-content-xxl-center{justify-content:center!important}.justify-content-xxl-between{justify-content:space-between!important}.justify-content-xxl-around{justify-content:space-around!important}.justify-content-xxl-evenly{justify-content:space-evenly!important}.align-items-xxl-start{align-items:flex-start!important}.align-items-xxl-end{align-items:flex-end!important}.align-items-xxl-center{align-items:center!important}.align-items-xxl-baseline{align-items:baseline!important}.align-items-xxl-stretch{align-items:stretch!important}.align-content-xxl-start{align-content:flex-start!important}.align-content-xxl-end{align-content:flex-end!important}.align-content-xxl-center{align-content:center!important}.align-content-xxl-between{align-content:space-between!important}.align-content-xxl-around{align-content:space-around!important}.align-content-xxl-stretch{align-content:stretch!important}.align-self-xxl-auto{align-self:auto!important}.align-self-xxl-start{align-self:flex-start!important}.align-self-xxl-end{align-self:flex-end!important}.align-self-xxl-center{align-self:center!important}.align-self-xxl-baseline{align-self:baseline!important}.align-self-xxl-stretch{align-self:stretch!important}.order-xxl-first{order:-1!important}.order-xxl-0{order:0!important}.order-xxl-1{order:1!important}.order-xxl-2{order:2!important}.order-xxl-3{order:3!important}.order-xxl-4{order:4!important}.order-xxl-5{order:5!important}.order-xxl-last{order:6!important}.m-xxl-0{margin:0!important}.m-xxl-1{margin:.25rem!important}.m-xxl-2{margin:.5rem!important}.m-xxl-3{margin:1rem!important}.m-xxl-4{margin:1.5rem!important}.m-xxl-5{margin:3rem!important}.m-xxl-auto{margin:auto!important}.mx-xxl-0{margin-right:0!important;margin-left:0!important}.mx-xxl-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-xxl-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-xxl-3{margin-right:1rem!important;margin-left:1rem!important}.mx-xxl-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-xxl-5{margin-right:3rem!important;margin-left:3rem!important}.mx-xxl-auto{margin-right:auto!important;margin-left:auto!important}.my-xxl-0{margin-top:0!important;margin-bottom:0!important}.my-xxl-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-xxl-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-xxl-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-xxl-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-xxl-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-xxl-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-xxl-0{margin-top:0!important}.mt-xxl-1{margin-top:.25rem!important}.mt-xxl-2{margin-top:.5rem!important}.mt-xxl-3{margin-top:1rem!important}.mt-xxl-4{margin-top:1.5rem!important}.mt-xxl-5{margin-top:3rem!important}.mt-xxl-auto{margin-top:auto!important}.me-xxl-0{margin-right:0!important}.me-xxl-1{margin-right:.25rem!important}.me-xxl-2{margin-right:.5rem!important}.me-xxl-3{margin-right:1rem!important}.me-xxl-4{margin-right:1.5rem!important}.me-xxl-5{margin-right:3rem!important}.me-xxl-auto{margin-right:auto!important}.mb-xxl-0{margin-bottom:0!important}.mb-xxl-1{margin-bottom:.25rem!important}.mb-xxl-2{margin-bottom:.5rem!important}.mb-xxl-3{margin-bottom:1rem!important}.mb-xxl-4{margin-bottom:1.5rem!important}.mb-xxl-5{margin-bottom:3rem!important}.mb-xxl-auto{margin-bottom:auto!important}.ms-xxl-0{margin-left:0!important}.ms-xxl-1{margin-left:.25rem!important}.ms-xxl-2{margin-left:.5rem!important}.ms-xxl-3{margin-left:1rem!important}.ms-xxl-4{margin-left:1.5rem!important}.ms-xxl-5{margin-left:3rem!important}.ms-xxl-auto{margin-left:auto!important}.p-xxl-0{padding:0!important}.p-xxl-1{padding:.25rem!important}.p-xxl-2{padding:.5rem!important}.p-xxl-3{padding:1rem!important}.p-xxl-4{padding:1.5rem!important}.p-xxl-5{padding:3rem!important}.px-xxl-0{padding-right:0!important;padding-left:0!important}.px-xxl-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-xxl-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-xxl-3{padding-right:1rem!important;padding-left:1rem!important}.px-xxl-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-xxl-5{padding-right:3rem!important;padding-left:3rem!important}.py-xxl-0{padding-top:0!important;padding-bottom:0!important}.py-xxl-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-xxl-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-xxl-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-xxl-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-xxl-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-xxl-0{padding-top:0!important}.pt-xxl-1{padding-top:.25rem!important}.pt-xxl-2{padding-top:.5rem!important}.pt-xxl-3{padding-top:1rem!important}.pt-xxl-4{padding-top:1.5rem!important}.pt-xxl-5{padding-top:3rem!important}.pe-xxl-0{padding-right:0!important}.pe-xxl-1{padding-right:.25rem!important}.pe-xxl-2{padding-right:.5rem!important}.pe-xxl-3{padding-right:1rem!important}.pe-xxl-4{padding-right:1.5rem!important}.pe-xxl-5{padding-right:3rem!important}.pb-xxl-0{padding-bottom:0!important}.pb-xxl-1{padding-bottom:.25rem!important}.pb-xxl-2{padding-bottom:.5rem!important}.pb-xxl-3{padding-bottom:1rem!important}.pb-xxl-4{padding-bottom:1.5rem!important}.pb-xxl-5{padding-bottom:3rem!important}.ps-xxl-0{padding-left:0!important}.ps-xxl-1{padding-left:.25rem!important}.ps-xxl-2{padding-left:.5rem!important}.ps-xxl-3{padding-left:1rem!important}.ps-xxl-4{padding-left:1.5rem!important}.ps-xxl-5{padding-left:3rem!important}.gap-xxl-0{gap:0!important}.gap-xxl-1{gap:.25rem!important}.gap-xxl-2{gap:.5rem!important}.gap-xxl-3{gap:1rem!important}.gap-xxl-4{gap:1.5rem!important}.gap-xxl-5{gap:3rem!important}.row-gap-xxl-0{row-gap:0!important}.row-gap-xxl-1{row-gap:.25rem!important}.row-gap-xxl-2{row-gap:.5rem!important}.row-gap-xxl-3{row-gap:1rem!important}.row-gap-xxl-4{row-gap:1.5rem!important}.row-gap-xxl-5{row-gap:3rem!important}.column-gap-xxl-0{-moz-column-gap:0!important;column-gap:0!important}.column-gap-xxl-1{-moz-column-gap:0.25rem!important;column-gap:.25rem!important}.column-gap-xxl-2{-moz-column-gap:0.5rem!important;column-gap:.5rem!important}.column-gap-xxl-3{-moz-column-gap:1rem!important;column-gap:1rem!important}.column-gap-xxl-4{-moz-column-gap:1.5rem!important;column-gap:1.5rem!important}.column-gap-xxl-5{-moz-column-gap:3rem!important;column-gap:3rem!important}.text-xxl-start{text-align:left!important}.text-xxl-end{text-align:right!important}.text-xxl-center{text-align:center!important}}@media (min-width:1200px){.fs-1{font-size:2.5rem!important}.fs-2{font-size:2rem!important}.fs-3{font-size:1.75rem!important}.fs-4{font-size:1.5rem!important}}@media print{.d-print-inline{display:inline!important}.d-print-inline-block{display:inline-block!important}.d-print-block{display:block!important}.d-print-grid{display:grid!important}.d-print-inline-grid{display:inline-grid!important}.d-print-table{display:table!important}.d-print-table-row{display:table-row!important}.d-print-table-cell{display:table-cell!important}.d-print-flex{display:flex!important}.d-print-inline-flex{display:inline-flex!important}.d-print-none{display:none!important}}.navbar.bg-primary{background-image:linear-gradient(#50b3eb,#2fa4e7 60%,#2c9ad9)}.navbar.bg-secondary{background-image:linear-gradient(#edeff2,#e9ecef 60%,#dbdee1)}.navbar.bg-success{background-image:linear-gradient(#89b659,#73a839 60%,#6c9e36)}.navbar.bg-info{background-image:linear-gradient(#2b5b89,#033c73 60%,#03386c)}.navbar.bg-warning{background-image:linear-gradient(#e27129,#dd5600 60%,#d05100)}.navbar.bg-danger{background-image:linear-gradient(#d04045,#c71c22 60%,#bb1a20)}.navbar.bg-light{background-image:linear-gradient(#f9fafb,#f8f9fa 60%,#e9eaeb)}.navbar.bg-dark{background-image:linear-gradient(#545a5f,#343a40 60%,#31373c)}.nav-link,.navbar-brand{text-shadow:0 1px 0 rgba(0,0,0,.05)}.btn{text-shadow:0 1px 0 rgba(0,0,0,.05)}.btn-outline-secondary,.btn-secondary{color:#495057}.btn-primary{background-image:linear-gradient(#50b3eb,#2fa4e7 60%,#2c9ad9)}.btn-secondary{background-image:linear-gradient(#edeff2,#e9ecef 60%,#dbdee1)}.btn-success{background-image:linear-gradient(#89b659,#73a839 60%,#6c9e36)}.btn-info{background-image:linear-gradient(#2b5b89,#033c73 60%,#03386c)}.btn-warning{background-image:linear-gradient(#e27129,#dd5600 60%,#d05100)}.btn-danger{background-image:linear-gradient(#d04045,#c71c22 60%,#bb1a20)}.btn-light{background-image:linear-gradient(#f9fafb,#f8f9fa 60%,#e9eaeb)}.btn-dark{background-image:linear-gradient(#545a5f,#343a40 60%,#31373c)}.text-secondary{color:#adb5bd!important}.bg-danger .h1,.bg-danger .h2,.bg-danger .h3,.bg-danger .h4,.bg-danger .h5,.bg-danger .h6,.bg-danger h1,.bg-danger h2,.bg-danger h3,.bg-danger h4,.bg-danger h5,.bg-danger h6,.bg-dark .h1,.bg-dark .h2,.bg-dark .h3,.bg-dark .h4,.bg-dark .h5,.bg-dark .h6,.bg-dark h1,.bg-dark h2,.bg-dark h3,.bg-dark h4,.bg-dark h5,.bg-dark h6,.bg-info .h1,.bg-info .h2,.bg-info .h3,.bg-info .h4,.bg-info .h5,.bg-info .h6,.bg-info h1,.bg-info h2,.bg-info h3,.bg-info h4,.bg-info h5,.bg-info h6,.bg-primary .h1,.bg-primary .h2,.bg-primary .h3,.bg-primary .h4,.bg-primary .h5,.bg-primary .h6,.bg-primary h1,.bg-primary h2,.bg-primary h3,.bg-primary h4,.bg-primary h5,.bg-primary h6,.bg-success .h1,.bg-success .h2,.bg-success .h3,.bg-success .h4,.bg-success .h5,.bg-success .h6,.bg-success h1,.bg-success h2,.bg-success h3,.bg-success h4,.bg-success h5,.bg-success h6,.bg-warning .h1,.bg-warning .h2,.bg-warning .h3,.bg-warning .h4,.bg-warning .h5,.bg-warning .h6,.bg-warning h1,.bg-warning h2,.bg-warning h3,.bg-warning h4,.bg-warning h5,.bg-warning h6{color:#fff}.dropdown-menu .dropdown-header{color:#868e96}.badge.bg-light,.badge.bg-secondary{color:#343a40} +/*# sourceMappingURL=bootstrap.min.css.map */ \ No newline at end of file diff --git a/css/bootstrap.min.css.map b/css/bootstrap.min.css.map new file mode 100644 index 00000000..45f32484 --- /dev/null +++ b/css/bootstrap.min.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["dist/cerulean/bootstrap.css"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/css/brands.min.css b/css/brands.min.css new file mode 100644 index 00000000..93a9a732 --- /dev/null +++ b/css/brands.min.css @@ -0,0 +1,6 @@ +/*! + * Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com + * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) + * Copyright 2023 Fonticons, Inc. + */ +:host,:root{--fa-style-family-brands:"Font Awesome 6 Brands";--fa-font-brands:normal 400 1em/1 "Font Awesome 6 Brands"}@font-face{font-family:"Font Awesome 6 Brands";font-style:normal;font-weight:400;font-display:block;src:url(../webfonts/fa-brands-400.woff2) format("woff2"),url(../webfonts/fa-brands-400.ttf) format("truetype")}.fa-brands,.fab{font-weight:400}.fa-monero:before{content:"\f3d0"}.fa-hooli:before{content:"\f427"}.fa-yelp:before{content:"\f1e9"}.fa-cc-visa:before{content:"\f1f0"}.fa-lastfm:before{content:"\f202"}.fa-shopware:before{content:"\f5b5"}.fa-creative-commons-nc:before{content:"\f4e8"}.fa-aws:before{content:"\f375"}.fa-redhat:before{content:"\f7bc"}.fa-yoast:before{content:"\f2b1"}.fa-cloudflare:before{content:"\e07d"}.fa-ups:before{content:"\f7e0"}.fa-pixiv:before{content:"\e640"}.fa-wpexplorer:before{content:"\f2de"}.fa-dyalog:before{content:"\f399"}.fa-bity:before{content:"\f37a"}.fa-stackpath:before{content:"\f842"}.fa-buysellads:before{content:"\f20d"}.fa-first-order:before{content:"\f2b0"}.fa-modx:before{content:"\f285"}.fa-guilded:before{content:"\e07e"}.fa-vnv:before{content:"\f40b"}.fa-js-square:before,.fa-square-js:before{content:"\f3b9"}.fa-microsoft:before{content:"\f3ca"}.fa-qq:before{content:"\f1d6"}.fa-orcid:before{content:"\f8d2"}.fa-java:before{content:"\f4e4"}.fa-invision:before{content:"\f7b0"}.fa-creative-commons-pd-alt:before{content:"\f4ed"}.fa-centercode:before{content:"\f380"}.fa-glide-g:before{content:"\f2a6"}.fa-drupal:before{content:"\f1a9"}.fa-hire-a-helper:before{content:"\f3b0"}.fa-creative-commons-by:before{content:"\f4e7"}.fa-unity:before{content:"\e049"}.fa-whmcs:before{content:"\f40d"}.fa-rocketchat:before{content:"\f3e8"}.fa-vk:before{content:"\f189"}.fa-untappd:before{content:"\f405"}.fa-mailchimp:before{content:"\f59e"}.fa-css3-alt:before{content:"\f38b"}.fa-reddit-square:before,.fa-square-reddit:before{content:"\f1a2"}.fa-vimeo-v:before{content:"\f27d"}.fa-contao:before{content:"\f26d"}.fa-square-font-awesome:before{content:"\e5ad"}.fa-deskpro:before{content:"\f38f"}.fa-brave:before{content:"\e63c"}.fa-sistrix:before{content:"\f3ee"}.fa-instagram-square:before,.fa-square-instagram:before{content:"\e055"}.fa-battle-net:before{content:"\f835"}.fa-the-red-yeti:before{content:"\f69d"}.fa-hacker-news-square:before,.fa-square-hacker-news:before{content:"\f3af"}.fa-edge:before{content:"\f282"}.fa-threads:before{content:"\e618"}.fa-napster:before{content:"\f3d2"}.fa-snapchat-square:before,.fa-square-snapchat:before{content:"\f2ad"}.fa-google-plus-g:before{content:"\f0d5"}.fa-artstation:before{content:"\f77a"}.fa-markdown:before{content:"\f60f"}.fa-sourcetree:before{content:"\f7d3"}.fa-google-plus:before{content:"\f2b3"}.fa-diaspora:before{content:"\f791"}.fa-foursquare:before{content:"\f180"}.fa-stack-overflow:before{content:"\f16c"}.fa-github-alt:before{content:"\f113"}.fa-phoenix-squadron:before{content:"\f511"}.fa-pagelines:before{content:"\f18c"}.fa-algolia:before{content:"\f36c"}.fa-red-river:before{content:"\f3e3"}.fa-creative-commons-sa:before{content:"\f4ef"}.fa-safari:before{content:"\f267"}.fa-google:before{content:"\f1a0"}.fa-font-awesome-alt:before,.fa-square-font-awesome-stroke:before{content:"\f35c"}.fa-atlassian:before{content:"\f77b"}.fa-linkedin-in:before{content:"\f0e1"}.fa-digital-ocean:before{content:"\f391"}.fa-nimblr:before{content:"\f5a8"}.fa-chromecast:before{content:"\f838"}.fa-evernote:before{content:"\f839"}.fa-hacker-news:before{content:"\f1d4"}.fa-creative-commons-sampling:before{content:"\f4f0"}.fa-adversal:before{content:"\f36a"}.fa-creative-commons:before{content:"\f25e"}.fa-watchman-monitoring:before{content:"\e087"}.fa-fonticons:before{content:"\f280"}.fa-weixin:before{content:"\f1d7"}.fa-shirtsinbulk:before{content:"\f214"}.fa-codepen:before{content:"\f1cb"}.fa-git-alt:before{content:"\f841"}.fa-lyft:before{content:"\f3c3"}.fa-rev:before{content:"\f5b2"}.fa-windows:before{content:"\f17a"}.fa-wizards-of-the-coast:before{content:"\f730"}.fa-square-viadeo:before,.fa-viadeo-square:before{content:"\f2aa"}.fa-meetup:before{content:"\f2e0"}.fa-centos:before{content:"\f789"}.fa-adn:before{content:"\f170"}.fa-cloudsmith:before{content:"\f384"}.fa-opensuse:before{content:"\e62b"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-dribbble-square:before,.fa-square-dribbble:before{content:"\f397"}.fa-codiepie:before{content:"\f284"}.fa-node:before{content:"\f419"}.fa-mix:before{content:"\f3cb"}.fa-steam:before{content:"\f1b6"}.fa-cc-apple-pay:before{content:"\f416"}.fa-scribd:before{content:"\f28a"}.fa-debian:before{content:"\e60b"}.fa-openid:before{content:"\f19b"}.fa-instalod:before{content:"\e081"}.fa-expeditedssl:before{content:"\f23e"}.fa-sellcast:before{content:"\f2da"}.fa-square-twitter:before,.fa-twitter-square:before{content:"\f081"}.fa-r-project:before{content:"\f4f7"}.fa-delicious:before{content:"\f1a5"}.fa-freebsd:before{content:"\f3a4"}.fa-vuejs:before{content:"\f41f"}.fa-accusoft:before{content:"\f369"}.fa-ioxhost:before{content:"\f208"}.fa-fonticons-fi:before{content:"\f3a2"}.fa-app-store:before{content:"\f36f"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-itunes-note:before{content:"\f3b5"}.fa-golang:before{content:"\e40f"}.fa-kickstarter:before{content:"\f3bb"}.fa-grav:before{content:"\f2d6"}.fa-weibo:before{content:"\f18a"}.fa-uncharted:before{content:"\e084"}.fa-firstdraft:before{content:"\f3a1"}.fa-square-youtube:before,.fa-youtube-square:before{content:"\f431"}.fa-wikipedia-w:before{content:"\f266"}.fa-rendact:before,.fa-wpressr:before{content:"\f3e4"}.fa-angellist:before{content:"\f209"}.fa-galactic-republic:before{content:"\f50c"}.fa-nfc-directional:before{content:"\e530"}.fa-skype:before{content:"\f17e"}.fa-joget:before{content:"\f3b7"}.fa-fedora:before{content:"\f798"}.fa-stripe-s:before{content:"\f42a"}.fa-meta:before{content:"\e49b"}.fa-laravel:before{content:"\f3bd"}.fa-hotjar:before{content:"\f3b1"}.fa-bluetooth-b:before{content:"\f294"}.fa-square-letterboxd:before{content:"\e62e"}.fa-sticker-mule:before{content:"\f3f7"}.fa-creative-commons-zero:before{content:"\f4f3"}.fa-hips:before{content:"\f452"}.fa-behance:before{content:"\f1b4"}.fa-reddit:before{content:"\f1a1"}.fa-discord:before{content:"\f392"}.fa-chrome:before{content:"\f268"}.fa-app-store-ios:before{content:"\f370"}.fa-cc-discover:before{content:"\f1f2"}.fa-wpbeginner:before{content:"\f297"}.fa-confluence:before{content:"\f78d"}.fa-shoelace:before{content:"\e60c"}.fa-mdb:before{content:"\f8ca"}.fa-dochub:before{content:"\f394"}.fa-accessible-icon:before{content:"\f368"}.fa-ebay:before{content:"\f4f4"}.fa-amazon:before{content:"\f270"}.fa-unsplash:before{content:"\e07c"}.fa-yarn:before{content:"\f7e3"}.fa-square-steam:before,.fa-steam-square:before{content:"\f1b7"}.fa-500px:before{content:"\f26e"}.fa-square-vimeo:before,.fa-vimeo-square:before{content:"\f194"}.fa-asymmetrik:before{content:"\f372"}.fa-font-awesome-flag:before,.fa-font-awesome-logo-full:before,.fa-font-awesome:before{content:"\f2b4"}.fa-gratipay:before{content:"\f184"}.fa-apple:before{content:"\f179"}.fa-hive:before{content:"\e07f"}.fa-gitkraken:before{content:"\f3a6"}.fa-keybase:before{content:"\f4f5"}.fa-apple-pay:before{content:"\f415"}.fa-padlet:before{content:"\e4a0"}.fa-amazon-pay:before{content:"\f42c"}.fa-github-square:before,.fa-square-github:before{content:"\f092"}.fa-stumbleupon:before{content:"\f1a4"}.fa-fedex:before{content:"\f797"}.fa-phoenix-framework:before{content:"\f3dc"}.fa-shopify:before{content:"\e057"}.fa-neos:before{content:"\f612"}.fa-square-threads:before{content:"\e619"}.fa-hackerrank:before{content:"\f5f7"}.fa-researchgate:before{content:"\f4f8"}.fa-swift:before{content:"\f8e1"}.fa-angular:before{content:"\f420"}.fa-speakap:before{content:"\f3f3"}.fa-angrycreative:before{content:"\f36e"}.fa-y-combinator:before{content:"\f23b"}.fa-empire:before{content:"\f1d1"}.fa-envira:before{content:"\f299"}.fa-google-scholar:before{content:"\e63b"}.fa-gitlab-square:before,.fa-square-gitlab:before{content:"\e5ae"}.fa-studiovinari:before{content:"\f3f8"}.fa-pied-piper:before{content:"\f2ae"}.fa-wordpress:before{content:"\f19a"}.fa-product-hunt:before{content:"\f288"}.fa-firefox:before{content:"\f269"}.fa-linode:before{content:"\f2b8"}.fa-goodreads:before{content:"\f3a8"}.fa-odnoklassniki-square:before,.fa-square-odnoklassniki:before{content:"\f264"}.fa-jsfiddle:before{content:"\f1cc"}.fa-sith:before{content:"\f512"}.fa-themeisle:before{content:"\f2b2"}.fa-page4:before{content:"\f3d7"}.fa-hashnode:before{content:"\e499"}.fa-react:before{content:"\f41b"}.fa-cc-paypal:before{content:"\f1f4"}.fa-squarespace:before{content:"\f5be"}.fa-cc-stripe:before{content:"\f1f5"}.fa-creative-commons-share:before{content:"\f4f2"}.fa-bitcoin:before{content:"\f379"}.fa-keycdn:before{content:"\f3ba"}.fa-opera:before{content:"\f26a"}.fa-itch-io:before{content:"\f83a"}.fa-umbraco:before{content:"\f8e8"}.fa-galactic-senate:before{content:"\f50d"}.fa-ubuntu:before{content:"\f7df"}.fa-draft2digital:before{content:"\f396"}.fa-stripe:before{content:"\f429"}.fa-houzz:before{content:"\f27c"}.fa-gg:before{content:"\f260"}.fa-dhl:before{content:"\f790"}.fa-pinterest-square:before,.fa-square-pinterest:before{content:"\f0d3"}.fa-xing:before{content:"\f168"}.fa-blackberry:before{content:"\f37b"}.fa-creative-commons-pd:before{content:"\f4ec"}.fa-playstation:before{content:"\f3df"}.fa-quinscape:before{content:"\f459"}.fa-less:before{content:"\f41d"}.fa-blogger-b:before{content:"\f37d"}.fa-opencart:before{content:"\f23d"}.fa-vine:before{content:"\f1ca"}.fa-signal-messenger:before{content:"\e663"}.fa-paypal:before{content:"\f1ed"}.fa-gitlab:before{content:"\f296"}.fa-typo3:before{content:"\f42b"}.fa-reddit-alien:before{content:"\f281"}.fa-yahoo:before{content:"\f19e"}.fa-dailymotion:before{content:"\e052"}.fa-affiliatetheme:before{content:"\f36b"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-bootstrap:before{content:"\f836"}.fa-odnoklassniki:before{content:"\f263"}.fa-nfc-symbol:before{content:"\e531"}.fa-mintbit:before{content:"\e62f"}.fa-ethereum:before{content:"\f42e"}.fa-speaker-deck:before{content:"\f83c"}.fa-creative-commons-nc-eu:before{content:"\f4e9"}.fa-patreon:before{content:"\f3d9"}.fa-avianex:before{content:"\f374"}.fa-ello:before{content:"\f5f1"}.fa-gofore:before{content:"\f3a7"}.fa-bimobject:before{content:"\f378"}.fa-brave-reverse:before{content:"\e63d"}.fa-facebook-f:before{content:"\f39e"}.fa-google-plus-square:before,.fa-square-google-plus:before{content:"\f0d4"}.fa-mandalorian:before{content:"\f50f"}.fa-first-order-alt:before{content:"\f50a"}.fa-osi:before{content:"\f41a"}.fa-google-wallet:before{content:"\f1ee"}.fa-d-and-d-beyond:before{content:"\f6ca"}.fa-periscope:before{content:"\f3da"}.fa-fulcrum:before{content:"\f50b"}.fa-cloudscale:before{content:"\f383"}.fa-forumbee:before{content:"\f211"}.fa-mizuni:before{content:"\f3cc"}.fa-schlix:before{content:"\f3ea"}.fa-square-xing:before,.fa-xing-square:before{content:"\f169"}.fa-bandcamp:before{content:"\f2d5"}.fa-wpforms:before{content:"\f298"}.fa-cloudversify:before{content:"\f385"}.fa-usps:before{content:"\f7e1"}.fa-megaport:before{content:"\f5a3"}.fa-magento:before{content:"\f3c4"}.fa-spotify:before{content:"\f1bc"}.fa-optin-monster:before{content:"\f23c"}.fa-fly:before{content:"\f417"}.fa-aviato:before{content:"\f421"}.fa-itunes:before{content:"\f3b4"}.fa-cuttlefish:before{content:"\f38c"}.fa-blogger:before{content:"\f37c"}.fa-flickr:before{content:"\f16e"}.fa-viber:before{content:"\f409"}.fa-soundcloud:before{content:"\f1be"}.fa-digg:before{content:"\f1a6"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-letterboxd:before{content:"\e62d"}.fa-symfony:before{content:"\f83d"}.fa-maxcdn:before{content:"\f136"}.fa-etsy:before{content:"\f2d7"}.fa-facebook-messenger:before{content:"\f39f"}.fa-audible:before{content:"\f373"}.fa-think-peaks:before{content:"\f731"}.fa-bilibili:before{content:"\e3d9"}.fa-erlang:before{content:"\f39d"}.fa-x-twitter:before{content:"\e61b"}.fa-cotton-bureau:before{content:"\f89e"}.fa-dashcube:before{content:"\f210"}.fa-42-group:before,.fa-innosoft:before{content:"\e080"}.fa-stack-exchange:before{content:"\f18d"}.fa-elementor:before{content:"\f430"}.fa-pied-piper-square:before,.fa-square-pied-piper:before{content:"\e01e"}.fa-creative-commons-nd:before{content:"\f4eb"}.fa-palfed:before{content:"\f3d8"}.fa-superpowers:before{content:"\f2dd"}.fa-resolving:before{content:"\f3e7"}.fa-xbox:before{content:"\f412"}.fa-searchengin:before{content:"\f3eb"}.fa-tiktok:before{content:"\e07b"}.fa-facebook-square:before,.fa-square-facebook:before{content:"\f082"}.fa-renren:before{content:"\f18b"}.fa-linux:before{content:"\f17c"}.fa-glide:before{content:"\f2a5"}.fa-linkedin:before{content:"\f08c"}.fa-hubspot:before{content:"\f3b2"}.fa-deploydog:before{content:"\f38e"}.fa-twitch:before{content:"\f1e8"}.fa-ravelry:before{content:"\f2d9"}.fa-mixer:before{content:"\e056"}.fa-lastfm-square:before,.fa-square-lastfm:before{content:"\f203"}.fa-vimeo:before{content:"\f40a"}.fa-mendeley:before{content:"\f7b3"}.fa-uniregistry:before{content:"\f404"}.fa-figma:before{content:"\f799"}.fa-creative-commons-remix:before{content:"\f4ee"}.fa-cc-amazon-pay:before{content:"\f42d"}.fa-dropbox:before{content:"\f16b"}.fa-instagram:before{content:"\f16d"}.fa-cmplid:before{content:"\e360"}.fa-upwork:before{content:"\e641"}.fa-facebook:before{content:"\f09a"}.fa-gripfire:before{content:"\f3ac"}.fa-jedi-order:before{content:"\f50e"}.fa-uikit:before{content:"\f403"}.fa-fort-awesome-alt:before{content:"\f3a3"}.fa-phabricator:before{content:"\f3db"}.fa-ussunnah:before{content:"\f407"}.fa-earlybirds:before{content:"\f39a"}.fa-trade-federation:before{content:"\f513"}.fa-autoprefixer:before{content:"\f41c"}.fa-whatsapp:before{content:"\f232"}.fa-slideshare:before{content:"\f1e7"}.fa-google-play:before{content:"\f3ab"}.fa-viadeo:before{content:"\f2a9"}.fa-line:before{content:"\f3c0"}.fa-google-drive:before{content:"\f3aa"}.fa-servicestack:before{content:"\f3ec"}.fa-simplybuilt:before{content:"\f215"}.fa-bitbucket:before{content:"\f171"}.fa-imdb:before{content:"\f2d8"}.fa-deezer:before{content:"\e077"}.fa-raspberry-pi:before{content:"\f7bb"}.fa-jira:before{content:"\f7b1"}.fa-docker:before{content:"\f395"}.fa-screenpal:before{content:"\e570"}.fa-bluetooth:before{content:"\f293"}.fa-gitter:before{content:"\f426"}.fa-d-and-d:before{content:"\f38d"}.fa-microblog:before{content:"\e01a"}.fa-cc-diners-club:before{content:"\f24c"}.fa-gg-circle:before{content:"\f261"}.fa-pied-piper-hat:before{content:"\f4e5"}.fa-kickstarter-k:before{content:"\f3bc"}.fa-yandex:before{content:"\f413"}.fa-readme:before{content:"\f4d5"}.fa-html5:before{content:"\f13b"}.fa-sellsy:before{content:"\f213"}.fa-sass:before{content:"\f41e"}.fa-wirsindhandwerk:before,.fa-wsh:before{content:"\e2d0"}.fa-buromobelexperte:before{content:"\f37f"}.fa-salesforce:before{content:"\f83b"}.fa-octopus-deploy:before{content:"\e082"}.fa-medapps:before{content:"\f3c6"}.fa-ns8:before{content:"\f3d5"}.fa-pinterest-p:before{content:"\f231"}.fa-apper:before{content:"\f371"}.fa-fort-awesome:before{content:"\f286"}.fa-waze:before{content:"\f83f"}.fa-cc-jcb:before{content:"\f24b"}.fa-snapchat-ghost:before,.fa-snapchat:before{content:"\f2ab"}.fa-fantasy-flight-games:before{content:"\f6dc"}.fa-rust:before{content:"\e07a"}.fa-wix:before{content:"\f5cf"}.fa-behance-square:before,.fa-square-behance:before{content:"\f1b5"}.fa-supple:before{content:"\f3f9"}.fa-webflow:before{content:"\e65c"}.fa-rebel:before{content:"\f1d0"}.fa-css3:before{content:"\f13c"}.fa-staylinked:before{content:"\f3f5"}.fa-kaggle:before{content:"\f5fa"}.fa-space-awesome:before{content:"\e5ac"}.fa-deviantart:before{content:"\f1bd"}.fa-cpanel:before{content:"\f388"}.fa-goodreads-g:before{content:"\f3a9"}.fa-git-square:before,.fa-square-git:before{content:"\f1d2"}.fa-square-tumblr:before,.fa-tumblr-square:before{content:"\f174"}.fa-trello:before{content:"\f181"}.fa-creative-commons-nc-jp:before{content:"\f4ea"}.fa-get-pocket:before{content:"\f265"}.fa-perbyte:before{content:"\e083"}.fa-grunt:before{content:"\f3ad"}.fa-weebly:before{content:"\f5cc"}.fa-connectdevelop:before{content:"\f20e"}.fa-leanpub:before{content:"\f212"}.fa-black-tie:before{content:"\f27e"}.fa-themeco:before{content:"\f5c6"}.fa-python:before{content:"\f3e2"}.fa-android:before{content:"\f17b"}.fa-bots:before{content:"\e340"}.fa-free-code-camp:before{content:"\f2c5"}.fa-hornbill:before{content:"\f592"}.fa-js:before{content:"\f3b8"}.fa-ideal:before{content:"\e013"}.fa-git:before{content:"\f1d3"}.fa-dev:before{content:"\f6cc"}.fa-sketch:before{content:"\f7c6"}.fa-yandex-international:before{content:"\f414"}.fa-cc-amex:before{content:"\f1f3"}.fa-uber:before{content:"\f402"}.fa-github:before{content:"\f09b"}.fa-php:before{content:"\f457"}.fa-alipay:before{content:"\f642"}.fa-youtube:before{content:"\f167"}.fa-skyatlas:before{content:"\f216"}.fa-firefox-browser:before{content:"\e007"}.fa-replyd:before{content:"\f3e6"}.fa-suse:before{content:"\f7d6"}.fa-jenkins:before{content:"\f3b6"}.fa-twitter:before{content:"\f099"}.fa-rockrms:before{content:"\f3e9"}.fa-pinterest:before{content:"\f0d2"}.fa-buffer:before{content:"\f837"}.fa-npm:before{content:"\f3d4"}.fa-yammer:before{content:"\f840"}.fa-btc:before{content:"\f15a"}.fa-dribbble:before{content:"\f17d"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-internet-explorer:before{content:"\f26b"}.fa-stubber:before{content:"\e5c7"}.fa-telegram-plane:before,.fa-telegram:before{content:"\f2c6"}.fa-old-republic:before{content:"\f510"}.fa-odysee:before{content:"\e5c6"}.fa-square-whatsapp:before,.fa-whatsapp-square:before{content:"\f40c"}.fa-node-js:before{content:"\f3d3"}.fa-edge-legacy:before{content:"\e078"}.fa-slack-hash:before,.fa-slack:before{content:"\f198"}.fa-medrt:before{content:"\f3c8"}.fa-usb:before{content:"\f287"}.fa-tumblr:before{content:"\f173"}.fa-vaadin:before{content:"\f408"}.fa-quora:before{content:"\f2c4"}.fa-square-x-twitter:before{content:"\e61a"}.fa-reacteurope:before{content:"\f75d"}.fa-medium-m:before,.fa-medium:before{content:"\f23a"}.fa-amilia:before{content:"\f36d"}.fa-mixcloud:before{content:"\f289"}.fa-flipboard:before{content:"\f44d"}.fa-viacoin:before{content:"\f237"}.fa-critical-role:before{content:"\f6c9"}.fa-sitrox:before{content:"\e44a"}.fa-discourse:before{content:"\f393"}.fa-joomla:before{content:"\f1aa"}.fa-mastodon:before{content:"\f4f6"}.fa-airbnb:before{content:"\f834"}.fa-wolf-pack-battalion:before{content:"\f514"}.fa-buy-n-large:before{content:"\f8a6"}.fa-gulp:before{content:"\f3ae"}.fa-creative-commons-sampling-plus:before{content:"\f4f1"}.fa-strava:before{content:"\f428"}.fa-ember:before{content:"\f423"}.fa-canadian-maple-leaf:before{content:"\f785"}.fa-teamspeak:before{content:"\f4f9"}.fa-pushed:before{content:"\f3e1"}.fa-wordpress-simple:before{content:"\f411"}.fa-nutritionix:before{content:"\f3d6"}.fa-wodu:before{content:"\e088"}.fa-google-pay:before{content:"\e079"}.fa-intercom:before{content:"\f7af"}.fa-zhihu:before{content:"\f63f"}.fa-korvue:before{content:"\f42f"}.fa-pix:before{content:"\e43a"}.fa-steam-symbol:before{content:"\f3f6"} \ No newline at end of file diff --git a/css/fontawesome.min.css b/css/fontawesome.min.css new file mode 100644 index 00000000..688dd75d --- /dev/null +++ b/css/fontawesome.min.css @@ -0,0 +1,9 @@ +/*! + * Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com + * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) + * Copyright 2023 Fonticons, Inc. + */ +.fa{font-family:var(--fa-style-family,"Font Awesome 6 Free");font-weight:var(--fa-style,900)}.fa,.fa-brands,.fa-classic,.fa-regular,.fa-sharp,.fa-solid,.fab,.far,.fas{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:var(--fa-display,inline-block);font-style:normal;font-variant:normal;line-height:1;text-rendering:auto}.fa-classic,.fa-regular,.fa-solid,.far,.fas{font-family:"Font Awesome 6 Free"}.fa-brands,.fab{font-family:"Font Awesome 6 Brands"}.fa-1x{font-size:1em}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-6x{font-size:6em}.fa-7x{font-size:7em}.fa-8x{font-size:8em}.fa-9x{font-size:9em}.fa-10x{font-size:10em}.fa-2xs{font-size:.625em;line-height:.1em;vertical-align:.225em}.fa-xs{font-size:.75em;line-height:.08333em;vertical-align:.125em}.fa-sm{font-size:.875em;line-height:.07143em;vertical-align:.05357em}.fa-lg{font-size:1.25em;line-height:.05em;vertical-align:-.075em}.fa-xl{font-size:1.5em;line-height:.04167em;vertical-align:-.125em}.fa-2xl{font-size:2em;line-height:.03125em;vertical-align:-.1875em}.fa-fw{text-align:center;width:1.25em}.fa-ul{list-style-type:none;margin-left:var(--fa-li-margin,2.5em);padding-left:0}.fa-ul>li{position:relative}.fa-li{left:calc(var(--fa-li-width, 2em)*-1);position:absolute;text-align:center;width:var(--fa-li-width,2em);line-height:inherit}.fa-border{border-radius:var(--fa-border-radius,.1em);border:var(--fa-border-width,.08em) var(--fa-border-style,solid) var(--fa-border-color,#eee);padding:var(--fa-border-padding,.2em .25em .15em)}.fa-pull-left{float:left;margin-right:var(--fa-pull-margin,.3em)}.fa-pull-right{float:right;margin-left:var(--fa-pull-margin,.3em)}.fa-beat{-webkit-animation-name:fa-beat;animation-name:fa-beat;-webkit-animation-delay:var(--fa-animation-delay,0s);animation-delay:var(--fa-animation-delay,0s);-webkit-animation-direction:var(--fa-animation-direction,normal);animation-direction:var(--fa-animation-direction,normal);-webkit-animation-duration:var(--fa-animation-duration,1s);animation-duration:var(--fa-animation-duration,1s);-webkit-animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-iteration-count:var(--fa-animation-iteration-count,infinite);-webkit-animation-timing-function:var(--fa-animation-timing,ease-in-out);animation-timing-function:var(--fa-animation-timing,ease-in-out)}.fa-bounce{-webkit-animation-name:fa-bounce;animation-name:fa-bounce;-webkit-animation-delay:var(--fa-animation-delay,0s);animation-delay:var(--fa-animation-delay,0s);-webkit-animation-direction:var(--fa-animation-direction,normal);animation-direction:var(--fa-animation-direction,normal);-webkit-animation-duration:var(--fa-animation-duration,1s);animation-duration:var(--fa-animation-duration,1s);-webkit-animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-iteration-count:var(--fa-animation-iteration-count,infinite);-webkit-animation-timing-function:var(--fa-animation-timing,cubic-bezier(.28,.84,.42,1));animation-timing-function:var(--fa-animation-timing,cubic-bezier(.28,.84,.42,1))}.fa-fade{-webkit-animation-name:fa-fade;animation-name:fa-fade;-webkit-animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-iteration-count:var(--fa-animation-iteration-count,infinite);-webkit-animation-timing-function:var(--fa-animation-timing,cubic-bezier(.4,0,.6,1));animation-timing-function:var(--fa-animation-timing,cubic-bezier(.4,0,.6,1))}.fa-beat-fade,.fa-fade{-webkit-animation-delay:var(--fa-animation-delay,0s);animation-delay:var(--fa-animation-delay,0s);-webkit-animation-direction:var(--fa-animation-direction,normal);animation-direction:var(--fa-animation-direction,normal);-webkit-animation-duration:var(--fa-animation-duration,1s);animation-duration:var(--fa-animation-duration,1s)}.fa-beat-fade{-webkit-animation-name:fa-beat-fade;animation-name:fa-beat-fade;-webkit-animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-iteration-count:var(--fa-animation-iteration-count,infinite);-webkit-animation-timing-function:var(--fa-animation-timing,cubic-bezier(.4,0,.6,1));animation-timing-function:var(--fa-animation-timing,cubic-bezier(.4,0,.6,1))}.fa-flip{-webkit-animation-name:fa-flip;animation-name:fa-flip;-webkit-animation-delay:var(--fa-animation-delay,0s);animation-delay:var(--fa-animation-delay,0s);-webkit-animation-direction:var(--fa-animation-direction,normal);animation-direction:var(--fa-animation-direction,normal);-webkit-animation-duration:var(--fa-animation-duration,1s);animation-duration:var(--fa-animation-duration,1s);-webkit-animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-iteration-count:var(--fa-animation-iteration-count,infinite);-webkit-animation-timing-function:var(--fa-animation-timing,ease-in-out);animation-timing-function:var(--fa-animation-timing,ease-in-out)}.fa-shake{-webkit-animation-name:fa-shake;animation-name:fa-shake;-webkit-animation-duration:var(--fa-animation-duration,1s);animation-duration:var(--fa-animation-duration,1s);-webkit-animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-iteration-count:var(--fa-animation-iteration-count,infinite);-webkit-animation-timing-function:var(--fa-animation-timing,linear);animation-timing-function:var(--fa-animation-timing,linear)}.fa-shake,.fa-spin{-webkit-animation-delay:var(--fa-animation-delay,0s);animation-delay:var(--fa-animation-delay,0s);-webkit-animation-direction:var(--fa-animation-direction,normal);animation-direction:var(--fa-animation-direction,normal)}.fa-spin{-webkit-animation-name:fa-spin;animation-name:fa-spin;-webkit-animation-duration:var(--fa-animation-duration,2s);animation-duration:var(--fa-animation-duration,2s);-webkit-animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-iteration-count:var(--fa-animation-iteration-count,infinite);-webkit-animation-timing-function:var(--fa-animation-timing,linear);animation-timing-function:var(--fa-animation-timing,linear)}.fa-spin-reverse{--fa-animation-direction:reverse}.fa-pulse,.fa-spin-pulse{-webkit-animation-name:fa-spin;animation-name:fa-spin;-webkit-animation-direction:var(--fa-animation-direction,normal);animation-direction:var(--fa-animation-direction,normal);-webkit-animation-duration:var(--fa-animation-duration,1s);animation-duration:var(--fa-animation-duration,1s);-webkit-animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-iteration-count:var(--fa-animation-iteration-count,infinite);-webkit-animation-timing-function:var(--fa-animation-timing,steps(8));animation-timing-function:var(--fa-animation-timing,steps(8))}@media (prefers-reduced-motion:reduce){.fa-beat,.fa-beat-fade,.fa-bounce,.fa-fade,.fa-flip,.fa-pulse,.fa-shake,.fa-spin,.fa-spin-pulse{-webkit-animation-delay:-1ms;animation-delay:-1ms;-webkit-animation-duration:1ms;animation-duration:1ms;-webkit-animation-iteration-count:1;animation-iteration-count:1;-webkit-transition-delay:0s;transition-delay:0s;-webkit-transition-duration:0s;transition-duration:0s}}@-webkit-keyframes fa-beat{0%,90%{-webkit-transform:scale(1);transform:scale(1)}45%{-webkit-transform:scale(var(--fa-beat-scale,1.25));transform:scale(var(--fa-beat-scale,1.25))}}@keyframes fa-beat{0%,90%{-webkit-transform:scale(1);transform:scale(1)}45%{-webkit-transform:scale(var(--fa-beat-scale,1.25));transform:scale(var(--fa-beat-scale,1.25))}}@-webkit-keyframes fa-bounce{0%{-webkit-transform:scale(1) translateY(0);transform:scale(1) translateY(0)}10%{-webkit-transform:scale(var(--fa-bounce-start-scale-x,1.1),var(--fa-bounce-start-scale-y,.9)) translateY(0);transform:scale(var(--fa-bounce-start-scale-x,1.1),var(--fa-bounce-start-scale-y,.9)) translateY(0)}30%{-webkit-transform:scale(var(--fa-bounce-jump-scale-x,.9),var(--fa-bounce-jump-scale-y,1.1)) translateY(var(--fa-bounce-height,-.5em));transform:scale(var(--fa-bounce-jump-scale-x,.9),var(--fa-bounce-jump-scale-y,1.1)) translateY(var(--fa-bounce-height,-.5em))}50%{-webkit-transform:scale(var(--fa-bounce-land-scale-x,1.05),var(--fa-bounce-land-scale-y,.95)) translateY(0);transform:scale(var(--fa-bounce-land-scale-x,1.05),var(--fa-bounce-land-scale-y,.95)) translateY(0)}57%{-webkit-transform:scale(1) translateY(var(--fa-bounce-rebound,-.125em));transform:scale(1) translateY(var(--fa-bounce-rebound,-.125em))}64%{-webkit-transform:scale(1) translateY(0);transform:scale(1) translateY(0)}to{-webkit-transform:scale(1) translateY(0);transform:scale(1) translateY(0)}}@keyframes fa-bounce{0%{-webkit-transform:scale(1) translateY(0);transform:scale(1) translateY(0)}10%{-webkit-transform:scale(var(--fa-bounce-start-scale-x,1.1),var(--fa-bounce-start-scale-y,.9)) translateY(0);transform:scale(var(--fa-bounce-start-scale-x,1.1),var(--fa-bounce-start-scale-y,.9)) translateY(0)}30%{-webkit-transform:scale(var(--fa-bounce-jump-scale-x,.9),var(--fa-bounce-jump-scale-y,1.1)) translateY(var(--fa-bounce-height,-.5em));transform:scale(var(--fa-bounce-jump-scale-x,.9),var(--fa-bounce-jump-scale-y,1.1)) translateY(var(--fa-bounce-height,-.5em))}50%{-webkit-transform:scale(var(--fa-bounce-land-scale-x,1.05),var(--fa-bounce-land-scale-y,.95)) translateY(0);transform:scale(var(--fa-bounce-land-scale-x,1.05),var(--fa-bounce-land-scale-y,.95)) translateY(0)}57%{-webkit-transform:scale(1) translateY(var(--fa-bounce-rebound,-.125em));transform:scale(1) translateY(var(--fa-bounce-rebound,-.125em))}64%{-webkit-transform:scale(1) translateY(0);transform:scale(1) translateY(0)}to{-webkit-transform:scale(1) translateY(0);transform:scale(1) translateY(0)}}@-webkit-keyframes fa-fade{50%{opacity:var(--fa-fade-opacity,.4)}}@keyframes fa-fade{50%{opacity:var(--fa-fade-opacity,.4)}}@-webkit-keyframes fa-beat-fade{0%,to{opacity:var(--fa-beat-fade-opacity,.4);-webkit-transform:scale(1);transform:scale(1)}50%{opacity:1;-webkit-transform:scale(var(--fa-beat-fade-scale,1.125));transform:scale(var(--fa-beat-fade-scale,1.125))}}@keyframes fa-beat-fade{0%,to{opacity:var(--fa-beat-fade-opacity,.4);-webkit-transform:scale(1);transform:scale(1)}50%{opacity:1;-webkit-transform:scale(var(--fa-beat-fade-scale,1.125));transform:scale(var(--fa-beat-fade-scale,1.125))}}@-webkit-keyframes fa-flip{50%{-webkit-transform:rotate3d(var(--fa-flip-x,0),var(--fa-flip-y,1),var(--fa-flip-z,0),var(--fa-flip-angle,-180deg));transform:rotate3d(var(--fa-flip-x,0),var(--fa-flip-y,1),var(--fa-flip-z,0),var(--fa-flip-angle,-180deg))}}@keyframes fa-flip{50%{-webkit-transform:rotate3d(var(--fa-flip-x,0),var(--fa-flip-y,1),var(--fa-flip-z,0),var(--fa-flip-angle,-180deg));transform:rotate3d(var(--fa-flip-x,0),var(--fa-flip-y,1),var(--fa-flip-z,0),var(--fa-flip-angle,-180deg))}}@-webkit-keyframes fa-shake{0%{-webkit-transform:rotate(-15deg);transform:rotate(-15deg)}4%{-webkit-transform:rotate(15deg);transform:rotate(15deg)}8%,24%{-webkit-transform:rotate(-18deg);transform:rotate(-18deg)}12%,28%{-webkit-transform:rotate(18deg);transform:rotate(18deg)}16%{-webkit-transform:rotate(-22deg);transform:rotate(-22deg)}20%{-webkit-transform:rotate(22deg);transform:rotate(22deg)}32%{-webkit-transform:rotate(-12deg);transform:rotate(-12deg)}36%{-webkit-transform:rotate(12deg);transform:rotate(12deg)}40%,to{-webkit-transform:rotate(0deg);transform:rotate(0deg)}}@keyframes fa-shake{0%{-webkit-transform:rotate(-15deg);transform:rotate(-15deg)}4%{-webkit-transform:rotate(15deg);transform:rotate(15deg)}8%,24%{-webkit-transform:rotate(-18deg);transform:rotate(-18deg)}12%,28%{-webkit-transform:rotate(18deg);transform:rotate(18deg)}16%{-webkit-transform:rotate(-22deg);transform:rotate(-22deg)}20%{-webkit-transform:rotate(22deg);transform:rotate(22deg)}32%{-webkit-transform:rotate(-12deg);transform:rotate(-12deg)}36%{-webkit-transform:rotate(12deg);transform:rotate(12deg)}40%,to{-webkit-transform:rotate(0deg);transform:rotate(0deg)}}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}.fa-rotate-90{-webkit-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-webkit-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-webkit-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-webkit-transform:scaleX(-1);transform:scaleX(-1)}.fa-flip-vertical{-webkit-transform:scaleY(-1);transform:scaleY(-1)}.fa-flip-both,.fa-flip-horizontal.fa-flip-vertical{-webkit-transform:scale(-1);transform:scale(-1)}.fa-rotate-by{-webkit-transform:rotate(var(--fa-rotate-angle,none));transform:rotate(var(--fa-rotate-angle,none))}.fa-stack{display:inline-block;height:2em;line-height:2em;position:relative;vertical-align:middle;width:2.5em}.fa-stack-1x,.fa-stack-2x{left:0;position:absolute;text-align:center;width:100%;z-index:var(--fa-stack-z-index,auto)}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:var(--fa-inverse,#fff)} + +.fa-0:before{content:"\30"}.fa-1:before{content:"\31"}.fa-2:before{content:"\32"}.fa-3:before{content:"\33"}.fa-4:before{content:"\34"}.fa-5:before{content:"\35"}.fa-6:before{content:"\36"}.fa-7:before{content:"\37"}.fa-8:before{content:"\38"}.fa-9:before{content:"\39"}.fa-fill-drip:before{content:"\f576"}.fa-arrows-to-circle:before{content:"\e4bd"}.fa-chevron-circle-right:before,.fa-circle-chevron-right:before{content:"\f138"}.fa-at:before{content:"\40"}.fa-trash-alt:before,.fa-trash-can:before{content:"\f2ed"}.fa-text-height:before{content:"\f034"}.fa-user-times:before,.fa-user-xmark:before{content:"\f235"}.fa-stethoscope:before{content:"\f0f1"}.fa-comment-alt:before,.fa-message:before{content:"\f27a"}.fa-info:before{content:"\f129"}.fa-compress-alt:before,.fa-down-left-and-up-right-to-center:before{content:"\f422"}.fa-explosion:before{content:"\e4e9"}.fa-file-alt:before,.fa-file-lines:before,.fa-file-text:before{content:"\f15c"}.fa-wave-square:before{content:"\f83e"}.fa-ring:before{content:"\f70b"}.fa-building-un:before{content:"\e4d9"}.fa-dice-three:before{content:"\f527"}.fa-calendar-alt:before,.fa-calendar-days:before{content:"\f073"}.fa-anchor-circle-check:before{content:"\e4aa"}.fa-building-circle-arrow-right:before{content:"\e4d1"}.fa-volleyball-ball:before,.fa-volleyball:before{content:"\f45f"}.fa-arrows-up-to-line:before{content:"\e4c2"}.fa-sort-desc:before,.fa-sort-down:before{content:"\f0dd"}.fa-circle-minus:before,.fa-minus-circle:before{content:"\f056"}.fa-door-open:before{content:"\f52b"}.fa-right-from-bracket:before,.fa-sign-out-alt:before{content:"\f2f5"}.fa-atom:before{content:"\f5d2"}.fa-soap:before{content:"\e06e"}.fa-heart-music-camera-bolt:before,.fa-icons:before{content:"\f86d"}.fa-microphone-alt-slash:before,.fa-microphone-lines-slash:before{content:"\f539"}.fa-bridge-circle-check:before{content:"\e4c9"}.fa-pump-medical:before{content:"\e06a"}.fa-fingerprint:before{content:"\f577"}.fa-hand-point-right:before{content:"\f0a4"}.fa-magnifying-glass-location:before,.fa-search-location:before{content:"\f689"}.fa-forward-step:before,.fa-step-forward:before{content:"\f051"}.fa-face-smile-beam:before,.fa-smile-beam:before{content:"\f5b8"}.fa-flag-checkered:before{content:"\f11e"}.fa-football-ball:before,.fa-football:before{content:"\f44e"}.fa-school-circle-exclamation:before{content:"\e56c"}.fa-crop:before{content:"\f125"}.fa-angle-double-down:before,.fa-angles-down:before{content:"\f103"}.fa-users-rectangle:before{content:"\e594"}.fa-people-roof:before{content:"\e537"}.fa-people-line:before{content:"\e534"}.fa-beer-mug-empty:before,.fa-beer:before{content:"\f0fc"}.fa-diagram-predecessor:before{content:"\e477"}.fa-arrow-up-long:before,.fa-long-arrow-up:before{content:"\f176"}.fa-burn:before,.fa-fire-flame-simple:before{content:"\f46a"}.fa-male:before,.fa-person:before{content:"\f183"}.fa-laptop:before{content:"\f109"}.fa-file-csv:before{content:"\f6dd"}.fa-menorah:before{content:"\f676"}.fa-truck-plane:before{content:"\e58f"}.fa-record-vinyl:before{content:"\f8d9"}.fa-face-grin-stars:before,.fa-grin-stars:before{content:"\f587"}.fa-bong:before{content:"\f55c"}.fa-pastafarianism:before,.fa-spaghetti-monster-flying:before{content:"\f67b"}.fa-arrow-down-up-across-line:before{content:"\e4af"}.fa-spoon:before,.fa-utensil-spoon:before{content:"\f2e5"}.fa-jar-wheat:before{content:"\e517"}.fa-envelopes-bulk:before,.fa-mail-bulk:before{content:"\f674"}.fa-file-circle-exclamation:before{content:"\e4eb"}.fa-circle-h:before,.fa-hospital-symbol:before{content:"\f47e"}.fa-pager:before{content:"\f815"}.fa-address-book:before,.fa-contact-book:before{content:"\f2b9"}.fa-strikethrough:before{content:"\f0cc"}.fa-k:before{content:"\4b"}.fa-landmark-flag:before{content:"\e51c"}.fa-pencil-alt:before,.fa-pencil:before{content:"\f303"}.fa-backward:before{content:"\f04a"}.fa-caret-right:before{content:"\f0da"}.fa-comments:before{content:"\f086"}.fa-file-clipboard:before,.fa-paste:before{content:"\f0ea"}.fa-code-pull-request:before{content:"\e13c"}.fa-clipboard-list:before{content:"\f46d"}.fa-truck-loading:before,.fa-truck-ramp-box:before{content:"\f4de"}.fa-user-check:before{content:"\f4fc"}.fa-vial-virus:before{content:"\e597"}.fa-sheet-plastic:before{content:"\e571"}.fa-blog:before{content:"\f781"}.fa-user-ninja:before{content:"\f504"}.fa-person-arrow-up-from-line:before{content:"\e539"}.fa-scroll-torah:before,.fa-torah:before{content:"\f6a0"}.fa-broom-ball:before,.fa-quidditch-broom-ball:before,.fa-quidditch:before{content:"\f458"}.fa-toggle-off:before{content:"\f204"}.fa-archive:before,.fa-box-archive:before{content:"\f187"}.fa-person-drowning:before{content:"\e545"}.fa-arrow-down-9-1:before,.fa-sort-numeric-desc:before,.fa-sort-numeric-down-alt:before{content:"\f886"}.fa-face-grin-tongue-squint:before,.fa-grin-tongue-squint:before{content:"\f58a"}.fa-spray-can:before{content:"\f5bd"}.fa-truck-monster:before{content:"\f63b"}.fa-w:before{content:"\57"}.fa-earth-africa:before,.fa-globe-africa:before{content:"\f57c"}.fa-rainbow:before{content:"\f75b"}.fa-circle-notch:before{content:"\f1ce"}.fa-tablet-alt:before,.fa-tablet-screen-button:before{content:"\f3fa"}.fa-paw:before{content:"\f1b0"}.fa-cloud:before{content:"\f0c2"}.fa-trowel-bricks:before{content:"\e58a"}.fa-face-flushed:before,.fa-flushed:before{content:"\f579"}.fa-hospital-user:before{content:"\f80d"}.fa-tent-arrow-left-right:before{content:"\e57f"}.fa-gavel:before,.fa-legal:before{content:"\f0e3"}.fa-binoculars:before{content:"\f1e5"}.fa-microphone-slash:before{content:"\f131"}.fa-box-tissue:before{content:"\e05b"}.fa-motorcycle:before{content:"\f21c"}.fa-bell-concierge:before,.fa-concierge-bell:before{content:"\f562"}.fa-pen-ruler:before,.fa-pencil-ruler:before{content:"\f5ae"}.fa-people-arrows-left-right:before,.fa-people-arrows:before{content:"\e068"}.fa-mars-and-venus-burst:before{content:"\e523"}.fa-caret-square-right:before,.fa-square-caret-right:before{content:"\f152"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-sun-plant-wilt:before{content:"\e57a"}.fa-toilets-portable:before{content:"\e584"}.fa-hockey-puck:before{content:"\f453"}.fa-table:before{content:"\f0ce"}.fa-magnifying-glass-arrow-right:before{content:"\e521"}.fa-digital-tachograph:before,.fa-tachograph-digital:before{content:"\f566"}.fa-users-slash:before{content:"\e073"}.fa-clover:before{content:"\e139"}.fa-mail-reply:before,.fa-reply:before{content:"\f3e5"}.fa-star-and-crescent:before{content:"\f699"}.fa-house-fire:before{content:"\e50c"}.fa-minus-square:before,.fa-square-minus:before{content:"\f146"}.fa-helicopter:before{content:"\f533"}.fa-compass:before{content:"\f14e"}.fa-caret-square-down:before,.fa-square-caret-down:before{content:"\f150"}.fa-file-circle-question:before{content:"\e4ef"}.fa-laptop-code:before{content:"\f5fc"}.fa-swatchbook:before{content:"\f5c3"}.fa-prescription-bottle:before{content:"\f485"}.fa-bars:before,.fa-navicon:before{content:"\f0c9"}.fa-people-group:before{content:"\e533"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\f253"}.fa-heart-broken:before,.fa-heart-crack:before{content:"\f7a9"}.fa-external-link-square-alt:before,.fa-square-up-right:before{content:"\f360"}.fa-face-kiss-beam:before,.fa-kiss-beam:before{content:"\f597"}.fa-film:before{content:"\f008"}.fa-ruler-horizontal:before{content:"\f547"}.fa-people-robbery:before{content:"\e536"}.fa-lightbulb:before{content:"\f0eb"}.fa-caret-left:before{content:"\f0d9"}.fa-circle-exclamation:before,.fa-exclamation-circle:before{content:"\f06a"}.fa-school-circle-xmark:before{content:"\e56d"}.fa-arrow-right-from-bracket:before,.fa-sign-out:before{content:"\f08b"}.fa-chevron-circle-down:before,.fa-circle-chevron-down:before{content:"\f13a"}.fa-unlock-alt:before,.fa-unlock-keyhole:before{content:"\f13e"}.fa-cloud-showers-heavy:before{content:"\f740"}.fa-headphones-alt:before,.fa-headphones-simple:before{content:"\f58f"}.fa-sitemap:before{content:"\f0e8"}.fa-circle-dollar-to-slot:before,.fa-donate:before{content:"\f4b9"}.fa-memory:before{content:"\f538"}.fa-road-spikes:before{content:"\e568"}.fa-fire-burner:before{content:"\e4f1"}.fa-flag:before{content:"\f024"}.fa-hanukiah:before{content:"\f6e6"}.fa-feather:before{content:"\f52d"}.fa-volume-down:before,.fa-volume-low:before{content:"\f027"}.fa-comment-slash:before{content:"\f4b3"}.fa-cloud-sun-rain:before{content:"\f743"}.fa-compress:before{content:"\f066"}.fa-wheat-alt:before,.fa-wheat-awn:before{content:"\e2cd"}.fa-ankh:before{content:"\f644"}.fa-hands-holding-child:before{content:"\e4fa"}.fa-asterisk:before{content:"\2a"}.fa-check-square:before,.fa-square-check:before{content:"\f14a"}.fa-peseta-sign:before{content:"\e221"}.fa-header:before,.fa-heading:before{content:"\f1dc"}.fa-ghost:before{content:"\f6e2"}.fa-list-squares:before,.fa-list:before{content:"\f03a"}.fa-phone-square-alt:before,.fa-square-phone-flip:before{content:"\f87b"}.fa-cart-plus:before{content:"\f217"}.fa-gamepad:before{content:"\f11b"}.fa-circle-dot:before,.fa-dot-circle:before{content:"\f192"}.fa-dizzy:before,.fa-face-dizzy:before{content:"\f567"}.fa-egg:before{content:"\f7fb"}.fa-house-medical-circle-xmark:before{content:"\e513"}.fa-campground:before{content:"\f6bb"}.fa-folder-plus:before{content:"\f65e"}.fa-futbol-ball:before,.fa-futbol:before,.fa-soccer-ball:before{content:"\f1e3"}.fa-paint-brush:before,.fa-paintbrush:before{content:"\f1fc"}.fa-lock:before{content:"\f023"}.fa-gas-pump:before{content:"\f52f"}.fa-hot-tub-person:before,.fa-hot-tub:before{content:"\f593"}.fa-map-location:before,.fa-map-marked:before{content:"\f59f"}.fa-house-flood-water:before{content:"\e50e"}.fa-tree:before{content:"\f1bb"}.fa-bridge-lock:before{content:"\e4cc"}.fa-sack-dollar:before{content:"\f81d"}.fa-edit:before,.fa-pen-to-square:before{content:"\f044"}.fa-car-side:before{content:"\f5e4"}.fa-share-alt:before,.fa-share-nodes:before{content:"\f1e0"}.fa-heart-circle-minus:before{content:"\e4ff"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\f252"}.fa-microscope:before{content:"\f610"}.fa-sink:before{content:"\e06d"}.fa-bag-shopping:before,.fa-shopping-bag:before{content:"\f290"}.fa-arrow-down-z-a:before,.fa-sort-alpha-desc:before,.fa-sort-alpha-down-alt:before{content:"\f881"}.fa-mitten:before{content:"\f7b5"}.fa-person-rays:before{content:"\e54d"}.fa-users:before{content:"\f0c0"}.fa-eye-slash:before{content:"\f070"}.fa-flask-vial:before{content:"\e4f3"}.fa-hand-paper:before,.fa-hand:before{content:"\f256"}.fa-om:before{content:"\f679"}.fa-worm:before{content:"\e599"}.fa-house-circle-xmark:before{content:"\e50b"}.fa-plug:before{content:"\f1e6"}.fa-chevron-up:before{content:"\f077"}.fa-hand-spock:before{content:"\f259"}.fa-stopwatch:before{content:"\f2f2"}.fa-face-kiss:before,.fa-kiss:before{content:"\f596"}.fa-bridge-circle-xmark:before{content:"\e4cb"}.fa-face-grin-tongue:before,.fa-grin-tongue:before{content:"\f589"}.fa-chess-bishop:before{content:"\f43a"}.fa-face-grin-wink:before,.fa-grin-wink:before{content:"\f58c"}.fa-deaf:before,.fa-deafness:before,.fa-ear-deaf:before,.fa-hard-of-hearing:before{content:"\f2a4"}.fa-road-circle-check:before{content:"\e564"}.fa-dice-five:before{content:"\f523"}.fa-rss-square:before,.fa-square-rss:before{content:"\f143"}.fa-land-mine-on:before{content:"\e51b"}.fa-i-cursor:before{content:"\f246"}.fa-stamp:before{content:"\f5bf"}.fa-stairs:before{content:"\e289"}.fa-i:before{content:"\49"}.fa-hryvnia-sign:before,.fa-hryvnia:before{content:"\f6f2"}.fa-pills:before{content:"\f484"}.fa-face-grin-wide:before,.fa-grin-alt:before{content:"\f581"}.fa-tooth:before{content:"\f5c9"}.fa-v:before{content:"\56"}.fa-bangladeshi-taka-sign:before{content:"\e2e6"}.fa-bicycle:before{content:"\f206"}.fa-rod-asclepius:before,.fa-rod-snake:before,.fa-staff-aesculapius:before,.fa-staff-snake:before{content:"\e579"}.fa-head-side-cough-slash:before{content:"\e062"}.fa-ambulance:before,.fa-truck-medical:before{content:"\f0f9"}.fa-wheat-awn-circle-exclamation:before{content:"\e598"}.fa-snowman:before{content:"\f7d0"}.fa-mortar-pestle:before{content:"\f5a7"}.fa-road-barrier:before{content:"\e562"}.fa-school:before{content:"\f549"}.fa-igloo:before{content:"\f7ae"}.fa-joint:before{content:"\f595"}.fa-angle-right:before{content:"\f105"}.fa-horse:before{content:"\f6f0"}.fa-q:before{content:"\51"}.fa-g:before{content:"\47"}.fa-notes-medical:before{content:"\f481"}.fa-temperature-2:before,.fa-temperature-half:before,.fa-thermometer-2:before,.fa-thermometer-half:before{content:"\f2c9"}.fa-dong-sign:before{content:"\e169"}.fa-capsules:before{content:"\f46b"}.fa-poo-bolt:before,.fa-poo-storm:before{content:"\f75a"}.fa-face-frown-open:before,.fa-frown-open:before{content:"\f57a"}.fa-hand-point-up:before{content:"\f0a6"}.fa-money-bill:before{content:"\f0d6"}.fa-bookmark:before{content:"\f02e"}.fa-align-justify:before{content:"\f039"}.fa-umbrella-beach:before{content:"\f5ca"}.fa-helmet-un:before{content:"\e503"}.fa-bullseye:before{content:"\f140"}.fa-bacon:before{content:"\f7e5"}.fa-hand-point-down:before{content:"\f0a7"}.fa-arrow-up-from-bracket:before{content:"\e09a"}.fa-folder-blank:before,.fa-folder:before{content:"\f07b"}.fa-file-medical-alt:before,.fa-file-waveform:before{content:"\f478"}.fa-radiation:before{content:"\f7b9"}.fa-chart-simple:before{content:"\e473"}.fa-mars-stroke:before{content:"\f229"}.fa-vial:before{content:"\f492"}.fa-dashboard:before,.fa-gauge-med:before,.fa-gauge:before,.fa-tachometer-alt-average:before{content:"\f624"}.fa-magic-wand-sparkles:before,.fa-wand-magic-sparkles:before{content:"\e2ca"}.fa-e:before{content:"\45"}.fa-pen-alt:before,.fa-pen-clip:before{content:"\f305"}.fa-bridge-circle-exclamation:before{content:"\e4ca"}.fa-user:before{content:"\f007"}.fa-school-circle-check:before{content:"\e56b"}.fa-dumpster:before{content:"\f793"}.fa-shuttle-van:before,.fa-van-shuttle:before{content:"\f5b6"}.fa-building-user:before{content:"\e4da"}.fa-caret-square-left:before,.fa-square-caret-left:before{content:"\f191"}.fa-highlighter:before{content:"\f591"}.fa-key:before{content:"\f084"}.fa-bullhorn:before{content:"\f0a1"}.fa-globe:before{content:"\f0ac"}.fa-synagogue:before{content:"\f69b"}.fa-person-half-dress:before{content:"\e548"}.fa-road-bridge:before{content:"\e563"}.fa-location-arrow:before{content:"\f124"}.fa-c:before{content:"\43"}.fa-tablet-button:before{content:"\f10a"}.fa-building-lock:before{content:"\e4d6"}.fa-pizza-slice:before{content:"\f818"}.fa-money-bill-wave:before{content:"\f53a"}.fa-area-chart:before,.fa-chart-area:before{content:"\f1fe"}.fa-house-flag:before{content:"\e50d"}.fa-person-circle-minus:before{content:"\e540"}.fa-ban:before,.fa-cancel:before{content:"\f05e"}.fa-camera-rotate:before{content:"\e0d8"}.fa-air-freshener:before,.fa-spray-can-sparkles:before{content:"\f5d0"}.fa-star:before{content:"\f005"}.fa-repeat:before{content:"\f363"}.fa-cross:before{content:"\f654"}.fa-box:before{content:"\f466"}.fa-venus-mars:before{content:"\f228"}.fa-arrow-pointer:before,.fa-mouse-pointer:before{content:"\f245"}.fa-expand-arrows-alt:before,.fa-maximize:before{content:"\f31e"}.fa-charging-station:before{content:"\f5e7"}.fa-shapes:before,.fa-triangle-circle-square:before{content:"\f61f"}.fa-random:before,.fa-shuffle:before{content:"\f074"}.fa-person-running:before,.fa-running:before{content:"\f70c"}.fa-mobile-retro:before{content:"\e527"}.fa-grip-lines-vertical:before{content:"\f7a5"}.fa-spider:before{content:"\f717"}.fa-hands-bound:before{content:"\e4f9"}.fa-file-invoice-dollar:before{content:"\f571"}.fa-plane-circle-exclamation:before{content:"\e556"}.fa-x-ray:before{content:"\f497"}.fa-spell-check:before{content:"\f891"}.fa-slash:before{content:"\f715"}.fa-computer-mouse:before,.fa-mouse:before{content:"\f8cc"}.fa-arrow-right-to-bracket:before,.fa-sign-in:before{content:"\f090"}.fa-shop-slash:before,.fa-store-alt-slash:before{content:"\e070"}.fa-server:before{content:"\f233"}.fa-virus-covid-slash:before{content:"\e4a9"}.fa-shop-lock:before{content:"\e4a5"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\f251"}.fa-blender-phone:before{content:"\f6b6"}.fa-building-wheat:before{content:"\e4db"}.fa-person-breastfeeding:before{content:"\e53a"}.fa-right-to-bracket:before,.fa-sign-in-alt:before{content:"\f2f6"}.fa-venus:before{content:"\f221"}.fa-passport:before{content:"\f5ab"}.fa-heart-pulse:before,.fa-heartbeat:before{content:"\f21e"}.fa-people-carry-box:before,.fa-people-carry:before{content:"\f4ce"}.fa-temperature-high:before{content:"\f769"}.fa-microchip:before{content:"\f2db"}.fa-crown:before{content:"\f521"}.fa-weight-hanging:before{content:"\f5cd"}.fa-xmarks-lines:before{content:"\e59a"}.fa-file-prescription:before{content:"\f572"}.fa-weight-scale:before,.fa-weight:before{content:"\f496"}.fa-user-friends:before,.fa-user-group:before{content:"\f500"}.fa-arrow-up-a-z:before,.fa-sort-alpha-up:before{content:"\f15e"}.fa-chess-knight:before{content:"\f441"}.fa-face-laugh-squint:before,.fa-laugh-squint:before{content:"\f59b"}.fa-wheelchair:before{content:"\f193"}.fa-arrow-circle-up:before,.fa-circle-arrow-up:before{content:"\f0aa"}.fa-toggle-on:before{content:"\f205"}.fa-person-walking:before,.fa-walking:before{content:"\f554"}.fa-l:before{content:"\4c"}.fa-fire:before{content:"\f06d"}.fa-bed-pulse:before,.fa-procedures:before{content:"\f487"}.fa-shuttle-space:before,.fa-space-shuttle:before{content:"\f197"}.fa-face-laugh:before,.fa-laugh:before{content:"\f599"}.fa-folder-open:before{content:"\f07c"}.fa-heart-circle-plus:before{content:"\e500"}.fa-code-fork:before{content:"\e13b"}.fa-city:before{content:"\f64f"}.fa-microphone-alt:before,.fa-microphone-lines:before{content:"\f3c9"}.fa-pepper-hot:before{content:"\f816"}.fa-unlock:before{content:"\f09c"}.fa-colon-sign:before{content:"\e140"}.fa-headset:before{content:"\f590"}.fa-store-slash:before{content:"\e071"}.fa-road-circle-xmark:before{content:"\e566"}.fa-user-minus:before{content:"\f503"}.fa-mars-stroke-up:before,.fa-mars-stroke-v:before{content:"\f22a"}.fa-champagne-glasses:before,.fa-glass-cheers:before{content:"\f79f"}.fa-clipboard:before{content:"\f328"}.fa-house-circle-exclamation:before{content:"\e50a"}.fa-file-arrow-up:before,.fa-file-upload:before{content:"\f574"}.fa-wifi-3:before,.fa-wifi-strong:before,.fa-wifi:before{content:"\f1eb"}.fa-bath:before,.fa-bathtub:before{content:"\f2cd"}.fa-underline:before{content:"\f0cd"}.fa-user-edit:before,.fa-user-pen:before{content:"\f4ff"}.fa-signature:before{content:"\f5b7"}.fa-stroopwafel:before{content:"\f551"}.fa-bold:before{content:"\f032"}.fa-anchor-lock:before{content:"\e4ad"}.fa-building-ngo:before{content:"\e4d7"}.fa-manat-sign:before{content:"\e1d5"}.fa-not-equal:before{content:"\f53e"}.fa-border-style:before,.fa-border-top-left:before{content:"\f853"}.fa-map-location-dot:before,.fa-map-marked-alt:before{content:"\f5a0"}.fa-jedi:before{content:"\f669"}.fa-poll:before,.fa-square-poll-vertical:before{content:"\f681"}.fa-mug-hot:before{content:"\f7b6"}.fa-battery-car:before,.fa-car-battery:before{content:"\f5df"}.fa-gift:before{content:"\f06b"}.fa-dice-two:before{content:"\f528"}.fa-chess-queen:before{content:"\f445"}.fa-glasses:before{content:"\f530"}.fa-chess-board:before{content:"\f43c"}.fa-building-circle-check:before{content:"\e4d2"}.fa-person-chalkboard:before{content:"\e53d"}.fa-mars-stroke-h:before,.fa-mars-stroke-right:before{content:"\f22b"}.fa-hand-back-fist:before,.fa-hand-rock:before{content:"\f255"}.fa-caret-square-up:before,.fa-square-caret-up:before{content:"\f151"}.fa-cloud-showers-water:before{content:"\e4e4"}.fa-bar-chart:before,.fa-chart-bar:before{content:"\f080"}.fa-hands-bubbles:before,.fa-hands-wash:before{content:"\e05e"}.fa-less-than-equal:before{content:"\f537"}.fa-train:before{content:"\f238"}.fa-eye-low-vision:before,.fa-low-vision:before{content:"\f2a8"}.fa-crow:before{content:"\f520"}.fa-sailboat:before{content:"\e445"}.fa-window-restore:before{content:"\f2d2"}.fa-plus-square:before,.fa-square-plus:before{content:"\f0fe"}.fa-torii-gate:before{content:"\f6a1"}.fa-frog:before{content:"\f52e"}.fa-bucket:before{content:"\e4cf"}.fa-image:before{content:"\f03e"}.fa-microphone:before{content:"\f130"}.fa-cow:before{content:"\f6c8"}.fa-caret-up:before{content:"\f0d8"}.fa-screwdriver:before{content:"\f54a"}.fa-folder-closed:before{content:"\e185"}.fa-house-tsunami:before{content:"\e515"}.fa-square-nfi:before{content:"\e576"}.fa-arrow-up-from-ground-water:before{content:"\e4b5"}.fa-glass-martini-alt:before,.fa-martini-glass:before{content:"\f57b"}.fa-rotate-back:before,.fa-rotate-backward:before,.fa-rotate-left:before,.fa-undo-alt:before{content:"\f2ea"}.fa-columns:before,.fa-table-columns:before{content:"\f0db"}.fa-lemon:before{content:"\f094"}.fa-head-side-mask:before{content:"\e063"}.fa-handshake:before{content:"\f2b5"}.fa-gem:before{content:"\f3a5"}.fa-dolly-box:before,.fa-dolly:before{content:"\f472"}.fa-smoking:before{content:"\f48d"}.fa-compress-arrows-alt:before,.fa-minimize:before{content:"\f78c"}.fa-monument:before{content:"\f5a6"}.fa-snowplow:before{content:"\f7d2"}.fa-angle-double-right:before,.fa-angles-right:before{content:"\f101"}.fa-cannabis:before{content:"\f55f"}.fa-circle-play:before,.fa-play-circle:before{content:"\f144"}.fa-tablets:before{content:"\f490"}.fa-ethernet:before{content:"\f796"}.fa-eur:before,.fa-euro-sign:before,.fa-euro:before{content:"\f153"}.fa-chair:before{content:"\f6c0"}.fa-check-circle:before,.fa-circle-check:before{content:"\f058"}.fa-circle-stop:before,.fa-stop-circle:before{content:"\f28d"}.fa-compass-drafting:before,.fa-drafting-compass:before{content:"\f568"}.fa-plate-wheat:before{content:"\e55a"}.fa-icicles:before{content:"\f7ad"}.fa-person-shelter:before{content:"\e54f"}.fa-neuter:before{content:"\f22c"}.fa-id-badge:before{content:"\f2c1"}.fa-marker:before{content:"\f5a1"}.fa-face-laugh-beam:before,.fa-laugh-beam:before{content:"\f59a"}.fa-helicopter-symbol:before{content:"\e502"}.fa-universal-access:before{content:"\f29a"}.fa-chevron-circle-up:before,.fa-circle-chevron-up:before{content:"\f139"}.fa-lari-sign:before{content:"\e1c8"}.fa-volcano:before{content:"\f770"}.fa-person-walking-dashed-line-arrow-right:before{content:"\e553"}.fa-gbp:before,.fa-pound-sign:before,.fa-sterling-sign:before{content:"\f154"}.fa-viruses:before{content:"\e076"}.fa-square-person-confined:before{content:"\e577"}.fa-user-tie:before{content:"\f508"}.fa-arrow-down-long:before,.fa-long-arrow-down:before{content:"\f175"}.fa-tent-arrow-down-to-line:before{content:"\e57e"}.fa-certificate:before{content:"\f0a3"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-suitcase:before{content:"\f0f2"}.fa-person-skating:before,.fa-skating:before{content:"\f7c5"}.fa-filter-circle-dollar:before,.fa-funnel-dollar:before{content:"\f662"}.fa-camera-retro:before{content:"\f083"}.fa-arrow-circle-down:before,.fa-circle-arrow-down:before{content:"\f0ab"}.fa-arrow-right-to-file:before,.fa-file-import:before{content:"\f56f"}.fa-external-link-square:before,.fa-square-arrow-up-right:before{content:"\f14c"}.fa-box-open:before{content:"\f49e"}.fa-scroll:before{content:"\f70e"}.fa-spa:before{content:"\f5bb"}.fa-location-pin-lock:before{content:"\e51f"}.fa-pause:before{content:"\f04c"}.fa-hill-avalanche:before{content:"\e507"}.fa-temperature-0:before,.fa-temperature-empty:before,.fa-thermometer-0:before,.fa-thermometer-empty:before{content:"\f2cb"}.fa-bomb:before{content:"\f1e2"}.fa-registered:before{content:"\f25d"}.fa-address-card:before,.fa-contact-card:before,.fa-vcard:before{content:"\f2bb"}.fa-balance-scale-right:before,.fa-scale-unbalanced-flip:before{content:"\f516"}.fa-subscript:before{content:"\f12c"}.fa-diamond-turn-right:before,.fa-directions:before{content:"\f5eb"}.fa-burst:before{content:"\e4dc"}.fa-house-laptop:before,.fa-laptop-house:before{content:"\e066"}.fa-face-tired:before,.fa-tired:before{content:"\f5c8"}.fa-money-bills:before{content:"\e1f3"}.fa-smog:before{content:"\f75f"}.fa-crutch:before{content:"\f7f7"}.fa-cloud-arrow-up:before,.fa-cloud-upload-alt:before,.fa-cloud-upload:before{content:"\f0ee"}.fa-palette:before{content:"\f53f"}.fa-arrows-turn-right:before{content:"\e4c0"}.fa-vest:before{content:"\e085"}.fa-ferry:before{content:"\e4ea"}.fa-arrows-down-to-people:before{content:"\e4b9"}.fa-seedling:before,.fa-sprout:before{content:"\f4d8"}.fa-arrows-alt-h:before,.fa-left-right:before{content:"\f337"}.fa-boxes-packing:before{content:"\e4c7"}.fa-arrow-circle-left:before,.fa-circle-arrow-left:before{content:"\f0a8"}.fa-group-arrows-rotate:before{content:"\e4f6"}.fa-bowl-food:before{content:"\e4c6"}.fa-candy-cane:before{content:"\f786"}.fa-arrow-down-wide-short:before,.fa-sort-amount-asc:before,.fa-sort-amount-down:before{content:"\f160"}.fa-cloud-bolt:before,.fa-thunderstorm:before{content:"\f76c"}.fa-remove-format:before,.fa-text-slash:before{content:"\f87d"}.fa-face-smile-wink:before,.fa-smile-wink:before{content:"\f4da"}.fa-file-word:before{content:"\f1c2"}.fa-file-powerpoint:before{content:"\f1c4"}.fa-arrows-h:before,.fa-arrows-left-right:before{content:"\f07e"}.fa-house-lock:before{content:"\e510"}.fa-cloud-arrow-down:before,.fa-cloud-download-alt:before,.fa-cloud-download:before{content:"\f0ed"}.fa-children:before{content:"\e4e1"}.fa-blackboard:before,.fa-chalkboard:before{content:"\f51b"}.fa-user-alt-slash:before,.fa-user-large-slash:before{content:"\f4fa"}.fa-envelope-open:before{content:"\f2b6"}.fa-handshake-alt-slash:before,.fa-handshake-simple-slash:before{content:"\e05f"}.fa-mattress-pillow:before{content:"\e525"}.fa-guarani-sign:before{content:"\e19a"}.fa-arrows-rotate:before,.fa-refresh:before,.fa-sync:before{content:"\f021"}.fa-fire-extinguisher:before{content:"\f134"}.fa-cruzeiro-sign:before{content:"\e152"}.fa-greater-than-equal:before{content:"\f532"}.fa-shield-alt:before,.fa-shield-halved:before{content:"\f3ed"}.fa-atlas:before,.fa-book-atlas:before{content:"\f558"}.fa-virus:before{content:"\e074"}.fa-envelope-circle-check:before{content:"\e4e8"}.fa-layer-group:before{content:"\f5fd"}.fa-arrows-to-dot:before{content:"\e4be"}.fa-archway:before{content:"\f557"}.fa-heart-circle-check:before{content:"\e4fd"}.fa-house-chimney-crack:before,.fa-house-damage:before{content:"\f6f1"}.fa-file-archive:before,.fa-file-zipper:before{content:"\f1c6"}.fa-square:before{content:"\f0c8"}.fa-glass-martini:before,.fa-martini-glass-empty:before{content:"\f000"}.fa-couch:before{content:"\f4b8"}.fa-cedi-sign:before{content:"\e0df"}.fa-italic:before{content:"\f033"}.fa-church:before{content:"\f51d"}.fa-comments-dollar:before{content:"\f653"}.fa-democrat:before{content:"\f747"}.fa-z:before{content:"\5a"}.fa-person-skiing:before,.fa-skiing:before{content:"\f7c9"}.fa-road-lock:before{content:"\e567"}.fa-a:before{content:"\41"}.fa-temperature-arrow-down:before,.fa-temperature-down:before{content:"\e03f"}.fa-feather-alt:before,.fa-feather-pointed:before{content:"\f56b"}.fa-p:before{content:"\50"}.fa-snowflake:before{content:"\f2dc"}.fa-newspaper:before{content:"\f1ea"}.fa-ad:before,.fa-rectangle-ad:before{content:"\f641"}.fa-arrow-circle-right:before,.fa-circle-arrow-right:before{content:"\f0a9"}.fa-filter-circle-xmark:before{content:"\e17b"}.fa-locust:before{content:"\e520"}.fa-sort:before,.fa-unsorted:before{content:"\f0dc"}.fa-list-1-2:before,.fa-list-numeric:before,.fa-list-ol:before{content:"\f0cb"}.fa-person-dress-burst:before{content:"\e544"}.fa-money-check-alt:before,.fa-money-check-dollar:before{content:"\f53d"}.fa-vector-square:before{content:"\f5cb"}.fa-bread-slice:before{content:"\f7ec"}.fa-language:before{content:"\f1ab"}.fa-face-kiss-wink-heart:before,.fa-kiss-wink-heart:before{content:"\f598"}.fa-filter:before{content:"\f0b0"}.fa-question:before{content:"\3f"}.fa-file-signature:before{content:"\f573"}.fa-arrows-alt:before,.fa-up-down-left-right:before{content:"\f0b2"}.fa-house-chimney-user:before{content:"\e065"}.fa-hand-holding-heart:before{content:"\f4be"}.fa-puzzle-piece:before{content:"\f12e"}.fa-money-check:before{content:"\f53c"}.fa-star-half-alt:before,.fa-star-half-stroke:before{content:"\f5c0"}.fa-code:before{content:"\f121"}.fa-glass-whiskey:before,.fa-whiskey-glass:before{content:"\f7a0"}.fa-building-circle-exclamation:before{content:"\e4d3"}.fa-magnifying-glass-chart:before{content:"\e522"}.fa-arrow-up-right-from-square:before,.fa-external-link:before{content:"\f08e"}.fa-cubes-stacked:before{content:"\e4e6"}.fa-krw:before,.fa-won-sign:before,.fa-won:before{content:"\f159"}.fa-virus-covid:before{content:"\e4a8"}.fa-austral-sign:before{content:"\e0a9"}.fa-f:before{content:"\46"}.fa-leaf:before{content:"\f06c"}.fa-road:before{content:"\f018"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-person-circle-plus:before{content:"\e541"}.fa-chart-pie:before,.fa-pie-chart:before{content:"\f200"}.fa-bolt-lightning:before{content:"\e0b7"}.fa-sack-xmark:before{content:"\e56a"}.fa-file-excel:before{content:"\f1c3"}.fa-file-contract:before{content:"\f56c"}.fa-fish-fins:before{content:"\e4f2"}.fa-building-flag:before{content:"\e4d5"}.fa-face-grin-beam:before,.fa-grin-beam:before{content:"\f582"}.fa-object-ungroup:before{content:"\f248"}.fa-poop:before{content:"\f619"}.fa-location-pin:before,.fa-map-marker:before{content:"\f041"}.fa-kaaba:before{content:"\f66b"}.fa-toilet-paper:before{content:"\f71e"}.fa-hard-hat:before,.fa-hat-hard:before,.fa-helmet-safety:before{content:"\f807"}.fa-eject:before{content:"\f052"}.fa-arrow-alt-circle-right:before,.fa-circle-right:before{content:"\f35a"}.fa-plane-circle-check:before{content:"\e555"}.fa-face-rolling-eyes:before,.fa-meh-rolling-eyes:before{content:"\f5a5"}.fa-object-group:before{content:"\f247"}.fa-chart-line:before,.fa-line-chart:before{content:"\f201"}.fa-mask-ventilator:before{content:"\e524"}.fa-arrow-right:before{content:"\f061"}.fa-map-signs:before,.fa-signs-post:before{content:"\f277"}.fa-cash-register:before{content:"\f788"}.fa-person-circle-question:before{content:"\e542"}.fa-h:before{content:"\48"}.fa-tarp:before{content:"\e57b"}.fa-screwdriver-wrench:before,.fa-tools:before{content:"\f7d9"}.fa-arrows-to-eye:before{content:"\e4bf"}.fa-plug-circle-bolt:before{content:"\e55b"}.fa-heart:before{content:"\f004"}.fa-mars-and-venus:before{content:"\f224"}.fa-home-user:before,.fa-house-user:before{content:"\e1b0"}.fa-dumpster-fire:before{content:"\f794"}.fa-house-crack:before{content:"\e3b1"}.fa-cocktail:before,.fa-martini-glass-citrus:before{content:"\f561"}.fa-face-surprise:before,.fa-surprise:before{content:"\f5c2"}.fa-bottle-water:before{content:"\e4c5"}.fa-circle-pause:before,.fa-pause-circle:before{content:"\f28b"}.fa-toilet-paper-slash:before{content:"\e072"}.fa-apple-alt:before,.fa-apple-whole:before{content:"\f5d1"}.fa-kitchen-set:before{content:"\e51a"}.fa-r:before{content:"\52"}.fa-temperature-1:before,.fa-temperature-quarter:before,.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:"\f2ca"}.fa-cube:before{content:"\f1b2"}.fa-bitcoin-sign:before{content:"\e0b4"}.fa-shield-dog:before{content:"\e573"}.fa-solar-panel:before{content:"\f5ba"}.fa-lock-open:before{content:"\f3c1"}.fa-elevator:before{content:"\e16d"}.fa-money-bill-transfer:before{content:"\e528"}.fa-money-bill-trend-up:before{content:"\e529"}.fa-house-flood-water-circle-arrow-right:before{content:"\e50f"}.fa-poll-h:before,.fa-square-poll-horizontal:before{content:"\f682"}.fa-circle:before{content:"\f111"}.fa-backward-fast:before,.fa-fast-backward:before{content:"\f049"}.fa-recycle:before{content:"\f1b8"}.fa-user-astronaut:before{content:"\f4fb"}.fa-plane-slash:before{content:"\e069"}.fa-trademark:before{content:"\f25c"}.fa-basketball-ball:before,.fa-basketball:before{content:"\f434"}.fa-satellite-dish:before{content:"\f7c0"}.fa-arrow-alt-circle-up:before,.fa-circle-up:before{content:"\f35b"}.fa-mobile-alt:before,.fa-mobile-screen-button:before{content:"\f3cd"}.fa-volume-high:before,.fa-volume-up:before{content:"\f028"}.fa-users-rays:before{content:"\e593"}.fa-wallet:before{content:"\f555"}.fa-clipboard-check:before{content:"\f46c"}.fa-file-audio:before{content:"\f1c7"}.fa-burger:before,.fa-hamburger:before{content:"\f805"}.fa-wrench:before{content:"\f0ad"}.fa-bugs:before{content:"\e4d0"}.fa-rupee-sign:before,.fa-rupee:before{content:"\f156"}.fa-file-image:before{content:"\f1c5"}.fa-circle-question:before,.fa-question-circle:before{content:"\f059"}.fa-plane-departure:before{content:"\f5b0"}.fa-handshake-slash:before{content:"\e060"}.fa-book-bookmark:before{content:"\e0bb"}.fa-code-branch:before{content:"\f126"}.fa-hat-cowboy:before{content:"\f8c0"}.fa-bridge:before{content:"\e4c8"}.fa-phone-alt:before,.fa-phone-flip:before{content:"\f879"}.fa-truck-front:before{content:"\e2b7"}.fa-cat:before{content:"\f6be"}.fa-anchor-circle-exclamation:before{content:"\e4ab"}.fa-truck-field:before{content:"\e58d"}.fa-route:before{content:"\f4d7"}.fa-clipboard-question:before{content:"\e4e3"}.fa-panorama:before{content:"\e209"}.fa-comment-medical:before{content:"\f7f5"}.fa-teeth-open:before{content:"\f62f"}.fa-file-circle-minus:before{content:"\e4ed"}.fa-tags:before{content:"\f02c"}.fa-wine-glass:before{content:"\f4e3"}.fa-fast-forward:before,.fa-forward-fast:before{content:"\f050"}.fa-face-meh-blank:before,.fa-meh-blank:before{content:"\f5a4"}.fa-parking:before,.fa-square-parking:before{content:"\f540"}.fa-house-signal:before{content:"\e012"}.fa-bars-progress:before,.fa-tasks-alt:before{content:"\f828"}.fa-faucet-drip:before{content:"\e006"}.fa-cart-flatbed:before,.fa-dolly-flatbed:before{content:"\f474"}.fa-ban-smoking:before,.fa-smoking-ban:before{content:"\f54d"}.fa-terminal:before{content:"\f120"}.fa-mobile-button:before{content:"\f10b"}.fa-house-medical-flag:before{content:"\e514"}.fa-basket-shopping:before,.fa-shopping-basket:before{content:"\f291"}.fa-tape:before{content:"\f4db"}.fa-bus-alt:before,.fa-bus-simple:before{content:"\f55e"}.fa-eye:before{content:"\f06e"}.fa-face-sad-cry:before,.fa-sad-cry:before{content:"\f5b3"}.fa-audio-description:before{content:"\f29e"}.fa-person-military-to-person:before{content:"\e54c"}.fa-file-shield:before{content:"\e4f0"}.fa-user-slash:before{content:"\f506"}.fa-pen:before{content:"\f304"}.fa-tower-observation:before{content:"\e586"}.fa-file-code:before{content:"\f1c9"}.fa-signal-5:before,.fa-signal-perfect:before,.fa-signal:before{content:"\f012"}.fa-bus:before{content:"\f207"}.fa-heart-circle-xmark:before{content:"\e501"}.fa-home-lg:before,.fa-house-chimney:before{content:"\e3af"}.fa-window-maximize:before{content:"\f2d0"}.fa-face-frown:before,.fa-frown:before{content:"\f119"}.fa-prescription:before{content:"\f5b1"}.fa-shop:before,.fa-store-alt:before{content:"\f54f"}.fa-floppy-disk:before,.fa-save:before{content:"\f0c7"}.fa-vihara:before{content:"\f6a7"}.fa-balance-scale-left:before,.fa-scale-unbalanced:before{content:"\f515"}.fa-sort-asc:before,.fa-sort-up:before{content:"\f0de"}.fa-comment-dots:before,.fa-commenting:before{content:"\f4ad"}.fa-plant-wilt:before{content:"\e5aa"}.fa-diamond:before{content:"\f219"}.fa-face-grin-squint:before,.fa-grin-squint:before{content:"\f585"}.fa-hand-holding-dollar:before,.fa-hand-holding-usd:before{content:"\f4c0"}.fa-bacterium:before{content:"\e05a"}.fa-hand-pointer:before{content:"\f25a"}.fa-drum-steelpan:before{content:"\f56a"}.fa-hand-scissors:before{content:"\f257"}.fa-hands-praying:before,.fa-praying-hands:before{content:"\f684"}.fa-arrow-right-rotate:before,.fa-arrow-rotate-forward:before,.fa-arrow-rotate-right:before,.fa-redo:before{content:"\f01e"}.fa-biohazard:before{content:"\f780"}.fa-location-crosshairs:before,.fa-location:before{content:"\f601"}.fa-mars-double:before{content:"\f227"}.fa-child-dress:before{content:"\e59c"}.fa-users-between-lines:before{content:"\e591"}.fa-lungs-virus:before{content:"\e067"}.fa-face-grin-tears:before,.fa-grin-tears:before{content:"\f588"}.fa-phone:before{content:"\f095"}.fa-calendar-times:before,.fa-calendar-xmark:before{content:"\f273"}.fa-child-reaching:before{content:"\e59d"}.fa-head-side-virus:before{content:"\e064"}.fa-user-cog:before,.fa-user-gear:before{content:"\f4fe"}.fa-arrow-up-1-9:before,.fa-sort-numeric-up:before{content:"\f163"}.fa-door-closed:before{content:"\f52a"}.fa-shield-virus:before{content:"\e06c"}.fa-dice-six:before{content:"\f526"}.fa-mosquito-net:before{content:"\e52c"}.fa-bridge-water:before{content:"\e4ce"}.fa-person-booth:before{content:"\f756"}.fa-text-width:before{content:"\f035"}.fa-hat-wizard:before{content:"\f6e8"}.fa-pen-fancy:before{content:"\f5ac"}.fa-digging:before,.fa-person-digging:before{content:"\f85e"}.fa-trash:before{content:"\f1f8"}.fa-gauge-simple-med:before,.fa-gauge-simple:before,.fa-tachometer-average:before{content:"\f629"}.fa-book-medical:before{content:"\f7e6"}.fa-poo:before{content:"\f2fe"}.fa-quote-right-alt:before,.fa-quote-right:before{content:"\f10e"}.fa-shirt:before,.fa-t-shirt:before,.fa-tshirt:before{content:"\f553"}.fa-cubes:before{content:"\f1b3"}.fa-divide:before{content:"\f529"}.fa-tenge-sign:before,.fa-tenge:before{content:"\f7d7"}.fa-headphones:before{content:"\f025"}.fa-hands-holding:before{content:"\f4c2"}.fa-hands-clapping:before{content:"\e1a8"}.fa-republican:before{content:"\f75e"}.fa-arrow-left:before{content:"\f060"}.fa-person-circle-xmark:before{content:"\e543"}.fa-ruler:before{content:"\f545"}.fa-align-left:before{content:"\f036"}.fa-dice-d6:before{content:"\f6d1"}.fa-restroom:before{content:"\f7bd"}.fa-j:before{content:"\4a"}.fa-users-viewfinder:before{content:"\e595"}.fa-file-video:before{content:"\f1c8"}.fa-external-link-alt:before,.fa-up-right-from-square:before{content:"\f35d"}.fa-table-cells:before,.fa-th:before{content:"\f00a"}.fa-file-pdf:before{content:"\f1c1"}.fa-bible:before,.fa-book-bible:before{content:"\f647"}.fa-o:before{content:"\4f"}.fa-medkit:before,.fa-suitcase-medical:before{content:"\f0fa"}.fa-user-secret:before{content:"\f21b"}.fa-otter:before{content:"\f700"}.fa-female:before,.fa-person-dress:before{content:"\f182"}.fa-comment-dollar:before{content:"\f651"}.fa-briefcase-clock:before,.fa-business-time:before{content:"\f64a"}.fa-table-cells-large:before,.fa-th-large:before{content:"\f009"}.fa-book-tanakh:before,.fa-tanakh:before{content:"\f827"}.fa-phone-volume:before,.fa-volume-control-phone:before{content:"\f2a0"}.fa-hat-cowboy-side:before{content:"\f8c1"}.fa-clipboard-user:before{content:"\f7f3"}.fa-child:before{content:"\f1ae"}.fa-lira-sign:before{content:"\f195"}.fa-satellite:before{content:"\f7bf"}.fa-plane-lock:before{content:"\e558"}.fa-tag:before{content:"\f02b"}.fa-comment:before{content:"\f075"}.fa-birthday-cake:before,.fa-cake-candles:before,.fa-cake:before{content:"\f1fd"}.fa-envelope:before{content:"\f0e0"}.fa-angle-double-up:before,.fa-angles-up:before{content:"\f102"}.fa-paperclip:before{content:"\f0c6"}.fa-arrow-right-to-city:before{content:"\e4b3"}.fa-ribbon:before{content:"\f4d6"}.fa-lungs:before{content:"\f604"}.fa-arrow-up-9-1:before,.fa-sort-numeric-up-alt:before{content:"\f887"}.fa-litecoin-sign:before{content:"\e1d3"}.fa-border-none:before{content:"\f850"}.fa-circle-nodes:before{content:"\e4e2"}.fa-parachute-box:before{content:"\f4cd"}.fa-indent:before{content:"\f03c"}.fa-truck-field-un:before{content:"\e58e"}.fa-hourglass-empty:before,.fa-hourglass:before{content:"\f254"}.fa-mountain:before{content:"\f6fc"}.fa-user-doctor:before,.fa-user-md:before{content:"\f0f0"}.fa-circle-info:before,.fa-info-circle:before{content:"\f05a"}.fa-cloud-meatball:before{content:"\f73b"}.fa-camera-alt:before,.fa-camera:before{content:"\f030"}.fa-square-virus:before{content:"\e578"}.fa-meteor:before{content:"\f753"}.fa-car-on:before{content:"\e4dd"}.fa-sleigh:before{content:"\f7cc"}.fa-arrow-down-1-9:before,.fa-sort-numeric-asc:before,.fa-sort-numeric-down:before{content:"\f162"}.fa-hand-holding-droplet:before,.fa-hand-holding-water:before{content:"\f4c1"}.fa-water:before{content:"\f773"}.fa-calendar-check:before{content:"\f274"}.fa-braille:before{content:"\f2a1"}.fa-prescription-bottle-alt:before,.fa-prescription-bottle-medical:before{content:"\f486"}.fa-landmark:before{content:"\f66f"}.fa-truck:before{content:"\f0d1"}.fa-crosshairs:before{content:"\f05b"}.fa-person-cane:before{content:"\e53c"}.fa-tent:before{content:"\e57d"}.fa-vest-patches:before{content:"\e086"}.fa-check-double:before{content:"\f560"}.fa-arrow-down-a-z:before,.fa-sort-alpha-asc:before,.fa-sort-alpha-down:before{content:"\f15d"}.fa-money-bill-wheat:before{content:"\e52a"}.fa-cookie:before{content:"\f563"}.fa-arrow-left-rotate:before,.fa-arrow-rotate-back:before,.fa-arrow-rotate-backward:before,.fa-arrow-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-hard-drive:before,.fa-hdd:before{content:"\f0a0"}.fa-face-grin-squint-tears:before,.fa-grin-squint-tears:before{content:"\f586"}.fa-dumbbell:before{content:"\f44b"}.fa-list-alt:before,.fa-rectangle-list:before{content:"\f022"}.fa-tarp-droplet:before{content:"\e57c"}.fa-house-medical-circle-check:before{content:"\e511"}.fa-person-skiing-nordic:before,.fa-skiing-nordic:before{content:"\f7ca"}.fa-calendar-plus:before{content:"\f271"}.fa-plane-arrival:before{content:"\f5af"}.fa-arrow-alt-circle-left:before,.fa-circle-left:before{content:"\f359"}.fa-subway:before,.fa-train-subway:before{content:"\f239"}.fa-chart-gantt:before{content:"\e0e4"}.fa-indian-rupee-sign:before,.fa-indian-rupee:before,.fa-inr:before{content:"\e1bc"}.fa-crop-alt:before,.fa-crop-simple:before{content:"\f565"}.fa-money-bill-1:before,.fa-money-bill-alt:before{content:"\f3d1"}.fa-left-long:before,.fa-long-arrow-alt-left:before{content:"\f30a"}.fa-dna:before{content:"\f471"}.fa-virus-slash:before{content:"\e075"}.fa-minus:before,.fa-subtract:before{content:"\f068"}.fa-chess:before{content:"\f439"}.fa-arrow-left-long:before,.fa-long-arrow-left:before{content:"\f177"}.fa-plug-circle-check:before{content:"\e55c"}.fa-street-view:before{content:"\f21d"}.fa-franc-sign:before{content:"\e18f"}.fa-volume-off:before{content:"\f026"}.fa-american-sign-language-interpreting:before,.fa-asl-interpreting:before,.fa-hands-american-sign-language-interpreting:before,.fa-hands-asl-interpreting:before{content:"\f2a3"}.fa-cog:before,.fa-gear:before{content:"\f013"}.fa-droplet-slash:before,.fa-tint-slash:before{content:"\f5c7"}.fa-mosque:before{content:"\f678"}.fa-mosquito:before{content:"\e52b"}.fa-star-of-david:before{content:"\f69a"}.fa-person-military-rifle:before{content:"\e54b"}.fa-cart-shopping:before,.fa-shopping-cart:before{content:"\f07a"}.fa-vials:before{content:"\f493"}.fa-plug-circle-plus:before{content:"\e55f"}.fa-place-of-worship:before{content:"\f67f"}.fa-grip-vertical:before{content:"\f58e"}.fa-arrow-turn-up:before,.fa-level-up:before{content:"\f148"}.fa-u:before{content:"\55"}.fa-square-root-alt:before,.fa-square-root-variable:before{content:"\f698"}.fa-clock-four:before,.fa-clock:before{content:"\f017"}.fa-backward-step:before,.fa-step-backward:before{content:"\f048"}.fa-pallet:before{content:"\f482"}.fa-faucet:before{content:"\e005"}.fa-baseball-bat-ball:before{content:"\f432"}.fa-s:before{content:"\53"}.fa-timeline:before{content:"\e29c"}.fa-keyboard:before{content:"\f11c"}.fa-caret-down:before{content:"\f0d7"}.fa-clinic-medical:before,.fa-house-chimney-medical:before{content:"\f7f2"}.fa-temperature-3:before,.fa-temperature-three-quarters:before,.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:"\f2c8"}.fa-mobile-android-alt:before,.fa-mobile-screen:before{content:"\f3cf"}.fa-plane-up:before{content:"\e22d"}.fa-piggy-bank:before{content:"\f4d3"}.fa-battery-3:before,.fa-battery-half:before{content:"\f242"}.fa-mountain-city:before{content:"\e52e"}.fa-coins:before{content:"\f51e"}.fa-khanda:before{content:"\f66d"}.fa-sliders-h:before,.fa-sliders:before{content:"\f1de"}.fa-folder-tree:before{content:"\f802"}.fa-network-wired:before{content:"\f6ff"}.fa-map-pin:before{content:"\f276"}.fa-hamsa:before{content:"\f665"}.fa-cent-sign:before{content:"\e3f5"}.fa-flask:before{content:"\f0c3"}.fa-person-pregnant:before{content:"\e31e"}.fa-wand-sparkles:before{content:"\f72b"}.fa-ellipsis-v:before,.fa-ellipsis-vertical:before{content:"\f142"}.fa-ticket:before{content:"\f145"}.fa-power-off:before{content:"\f011"}.fa-long-arrow-alt-right:before,.fa-right-long:before{content:"\f30b"}.fa-flag-usa:before{content:"\f74d"}.fa-laptop-file:before{content:"\e51d"}.fa-teletype:before,.fa-tty:before{content:"\f1e4"}.fa-diagram-next:before{content:"\e476"}.fa-person-rifle:before{content:"\e54e"}.fa-house-medical-circle-exclamation:before{content:"\e512"}.fa-closed-captioning:before{content:"\f20a"}.fa-hiking:before,.fa-person-hiking:before{content:"\f6ec"}.fa-venus-double:before{content:"\f226"}.fa-images:before{content:"\f302"}.fa-calculator:before{content:"\f1ec"}.fa-people-pulling:before{content:"\e535"}.fa-n:before{content:"\4e"}.fa-cable-car:before,.fa-tram:before{content:"\f7da"}.fa-cloud-rain:before{content:"\f73d"}.fa-building-circle-xmark:before{content:"\e4d4"}.fa-ship:before{content:"\f21a"}.fa-arrows-down-to-line:before{content:"\e4b8"}.fa-download:before{content:"\f019"}.fa-face-grin:before,.fa-grin:before{content:"\f580"}.fa-backspace:before,.fa-delete-left:before{content:"\f55a"}.fa-eye-dropper-empty:before,.fa-eye-dropper:before,.fa-eyedropper:before{content:"\f1fb"}.fa-file-circle-check:before{content:"\e5a0"}.fa-forward:before{content:"\f04e"}.fa-mobile-android:before,.fa-mobile-phone:before,.fa-mobile:before{content:"\f3ce"}.fa-face-meh:before,.fa-meh:before{content:"\f11a"}.fa-align-center:before{content:"\f037"}.fa-book-dead:before,.fa-book-skull:before{content:"\f6b7"}.fa-drivers-license:before,.fa-id-card:before{content:"\f2c2"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-heart-circle-exclamation:before{content:"\e4fe"}.fa-home-alt:before,.fa-home-lg-alt:before,.fa-home:before,.fa-house:before{content:"\f015"}.fa-calendar-week:before{content:"\f784"}.fa-laptop-medical:before{content:"\f812"}.fa-b:before{content:"\42"}.fa-file-medical:before{content:"\f477"}.fa-dice-one:before{content:"\f525"}.fa-kiwi-bird:before{content:"\f535"}.fa-arrow-right-arrow-left:before,.fa-exchange:before{content:"\f0ec"}.fa-redo-alt:before,.fa-rotate-forward:before,.fa-rotate-right:before{content:"\f2f9"}.fa-cutlery:before,.fa-utensils:before{content:"\f2e7"}.fa-arrow-up-wide-short:before,.fa-sort-amount-up:before{content:"\f161"}.fa-mill-sign:before{content:"\e1ed"}.fa-bowl-rice:before{content:"\e2eb"}.fa-skull:before{content:"\f54c"}.fa-broadcast-tower:before,.fa-tower-broadcast:before{content:"\f519"}.fa-truck-pickup:before{content:"\f63c"}.fa-long-arrow-alt-up:before,.fa-up-long:before{content:"\f30c"}.fa-stop:before{content:"\f04d"}.fa-code-merge:before{content:"\f387"}.fa-upload:before{content:"\f093"}.fa-hurricane:before{content:"\f751"}.fa-mound:before{content:"\e52d"}.fa-toilet-portable:before{content:"\e583"}.fa-compact-disc:before{content:"\f51f"}.fa-file-arrow-down:before,.fa-file-download:before{content:"\f56d"}.fa-caravan:before{content:"\f8ff"}.fa-shield-cat:before{content:"\e572"}.fa-bolt:before,.fa-zap:before{content:"\f0e7"}.fa-glass-water:before{content:"\e4f4"}.fa-oil-well:before{content:"\e532"}.fa-vault:before{content:"\e2c5"}.fa-mars:before{content:"\f222"}.fa-toilet:before{content:"\f7d8"}.fa-plane-circle-xmark:before{content:"\e557"}.fa-cny:before,.fa-jpy:before,.fa-rmb:before,.fa-yen-sign:before,.fa-yen:before{content:"\f157"}.fa-rouble:before,.fa-rub:before,.fa-ruble-sign:before,.fa-ruble:before{content:"\f158"}.fa-sun:before{content:"\f185"}.fa-guitar:before{content:"\f7a6"}.fa-face-laugh-wink:before,.fa-laugh-wink:before{content:"\f59c"}.fa-horse-head:before{content:"\f7ab"}.fa-bore-hole:before{content:"\e4c3"}.fa-industry:before{content:"\f275"}.fa-arrow-alt-circle-down:before,.fa-circle-down:before{content:"\f358"}.fa-arrows-turn-to-dots:before{content:"\e4c1"}.fa-florin-sign:before{content:"\e184"}.fa-arrow-down-short-wide:before,.fa-sort-amount-desc:before,.fa-sort-amount-down-alt:before{content:"\f884"}.fa-less-than:before{content:"\3c"}.fa-angle-down:before{content:"\f107"}.fa-car-tunnel:before{content:"\e4de"}.fa-head-side-cough:before{content:"\e061"}.fa-grip-lines:before{content:"\f7a4"}.fa-thumbs-down:before{content:"\f165"}.fa-user-lock:before{content:"\f502"}.fa-arrow-right-long:before,.fa-long-arrow-right:before{content:"\f178"}.fa-anchor-circle-xmark:before{content:"\e4ac"}.fa-ellipsis-h:before,.fa-ellipsis:before{content:"\f141"}.fa-chess-pawn:before{content:"\f443"}.fa-first-aid:before,.fa-kit-medical:before{content:"\f479"}.fa-person-through-window:before{content:"\e5a9"}.fa-toolbox:before{content:"\f552"}.fa-hands-holding-circle:before{content:"\e4fb"}.fa-bug:before{content:"\f188"}.fa-credit-card-alt:before,.fa-credit-card:before{content:"\f09d"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-hand-holding-hand:before{content:"\e4f7"}.fa-book-open-reader:before,.fa-book-reader:before{content:"\f5da"}.fa-mountain-sun:before{content:"\e52f"}.fa-arrows-left-right-to-line:before{content:"\e4ba"}.fa-dice-d20:before{content:"\f6cf"}.fa-truck-droplet:before{content:"\e58c"}.fa-file-circle-xmark:before{content:"\e5a1"}.fa-temperature-arrow-up:before,.fa-temperature-up:before{content:"\e040"}.fa-medal:before{content:"\f5a2"}.fa-bed:before{content:"\f236"}.fa-h-square:before,.fa-square-h:before{content:"\f0fd"}.fa-podcast:before{content:"\f2ce"}.fa-temperature-4:before,.fa-temperature-full:before,.fa-thermometer-4:before,.fa-thermometer-full:before{content:"\f2c7"}.fa-bell:before{content:"\f0f3"}.fa-superscript:before{content:"\f12b"}.fa-plug-circle-xmark:before{content:"\e560"}.fa-star-of-life:before{content:"\f621"}.fa-phone-slash:before{content:"\f3dd"}.fa-paint-roller:before{content:"\f5aa"}.fa-hands-helping:before,.fa-handshake-angle:before{content:"\f4c4"}.fa-location-dot:before,.fa-map-marker-alt:before{content:"\f3c5"}.fa-file:before{content:"\f15b"}.fa-greater-than:before{content:"\3e"}.fa-person-swimming:before,.fa-swimmer:before{content:"\f5c4"}.fa-arrow-down:before{content:"\f063"}.fa-droplet:before,.fa-tint:before{content:"\f043"}.fa-eraser:before{content:"\f12d"}.fa-earth-america:before,.fa-earth-americas:before,.fa-earth:before,.fa-globe-americas:before{content:"\f57d"}.fa-person-burst:before{content:"\e53b"}.fa-dove:before{content:"\f4ba"}.fa-battery-0:before,.fa-battery-empty:before{content:"\f244"}.fa-socks:before{content:"\f696"}.fa-inbox:before{content:"\f01c"}.fa-section:before{content:"\e447"}.fa-gauge-high:before,.fa-tachometer-alt-fast:before,.fa-tachometer-alt:before{content:"\f625"}.fa-envelope-open-text:before{content:"\f658"}.fa-hospital-alt:before,.fa-hospital-wide:before,.fa-hospital:before{content:"\f0f8"}.fa-wine-bottle:before{content:"\f72f"}.fa-chess-rook:before{content:"\f447"}.fa-bars-staggered:before,.fa-reorder:before,.fa-stream:before{content:"\f550"}.fa-dharmachakra:before{content:"\f655"}.fa-hotdog:before{content:"\f80f"}.fa-blind:before,.fa-person-walking-with-cane:before{content:"\f29d"}.fa-drum:before{content:"\f569"}.fa-ice-cream:before{content:"\f810"}.fa-heart-circle-bolt:before{content:"\e4fc"}.fa-fax:before{content:"\f1ac"}.fa-paragraph:before{content:"\f1dd"}.fa-check-to-slot:before,.fa-vote-yea:before{content:"\f772"}.fa-star-half:before{content:"\f089"}.fa-boxes-alt:before,.fa-boxes-stacked:before,.fa-boxes:before{content:"\f468"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-assistive-listening-systems:before,.fa-ear-listen:before{content:"\f2a2"}.fa-tree-city:before{content:"\e587"}.fa-play:before{content:"\f04b"}.fa-font:before{content:"\f031"}.fa-rupiah-sign:before{content:"\e23d"}.fa-magnifying-glass:before,.fa-search:before{content:"\f002"}.fa-ping-pong-paddle-ball:before,.fa-table-tennis-paddle-ball:before,.fa-table-tennis:before{content:"\f45d"}.fa-diagnoses:before,.fa-person-dots-from-line:before{content:"\f470"}.fa-trash-can-arrow-up:before,.fa-trash-restore-alt:before{content:"\f82a"}.fa-naira-sign:before{content:"\e1f6"}.fa-cart-arrow-down:before{content:"\f218"}.fa-walkie-talkie:before{content:"\f8ef"}.fa-file-edit:before,.fa-file-pen:before{content:"\f31c"}.fa-receipt:before{content:"\f543"}.fa-pen-square:before,.fa-pencil-square:before,.fa-square-pen:before{content:"\f14b"}.fa-suitcase-rolling:before{content:"\f5c1"}.fa-person-circle-exclamation:before{content:"\e53f"}.fa-chevron-down:before{content:"\f078"}.fa-battery-5:before,.fa-battery-full:before,.fa-battery:before{content:"\f240"}.fa-skull-crossbones:before{content:"\f714"}.fa-code-compare:before{content:"\e13a"}.fa-list-dots:before,.fa-list-ul:before{content:"\f0ca"}.fa-school-lock:before{content:"\e56f"}.fa-tower-cell:before{content:"\e585"}.fa-down-long:before,.fa-long-arrow-alt-down:before{content:"\f309"}.fa-ranking-star:before{content:"\e561"}.fa-chess-king:before{content:"\f43f"}.fa-person-harassing:before{content:"\e549"}.fa-brazilian-real-sign:before{content:"\e46c"}.fa-landmark-alt:before,.fa-landmark-dome:before{content:"\f752"}.fa-arrow-up:before{content:"\f062"}.fa-television:before,.fa-tv-alt:before,.fa-tv:before{content:"\f26c"}.fa-shrimp:before{content:"\e448"}.fa-list-check:before,.fa-tasks:before{content:"\f0ae"}.fa-jug-detergent:before{content:"\e519"}.fa-circle-user:before,.fa-user-circle:before{content:"\f2bd"}.fa-user-shield:before{content:"\f505"}.fa-wind:before{content:"\f72e"}.fa-car-burst:before,.fa-car-crash:before{content:"\f5e1"}.fa-y:before{content:"\59"}.fa-person-snowboarding:before,.fa-snowboarding:before{content:"\f7ce"}.fa-shipping-fast:before,.fa-truck-fast:before{content:"\f48b"}.fa-fish:before{content:"\f578"}.fa-user-graduate:before{content:"\f501"}.fa-adjust:before,.fa-circle-half-stroke:before{content:"\f042"}.fa-clapperboard:before{content:"\e131"}.fa-circle-radiation:before,.fa-radiation-alt:before{content:"\f7ba"}.fa-baseball-ball:before,.fa-baseball:before{content:"\f433"}.fa-jet-fighter-up:before{content:"\e518"}.fa-diagram-project:before,.fa-project-diagram:before{content:"\f542"}.fa-copy:before{content:"\f0c5"}.fa-volume-mute:before,.fa-volume-times:before,.fa-volume-xmark:before{content:"\f6a9"}.fa-hand-sparkles:before{content:"\e05d"}.fa-grip-horizontal:before,.fa-grip:before{content:"\f58d"}.fa-share-from-square:before,.fa-share-square:before{content:"\f14d"}.fa-child-combatant:before,.fa-child-rifle:before{content:"\e4e0"}.fa-gun:before{content:"\e19b"}.fa-phone-square:before,.fa-square-phone:before{content:"\f098"}.fa-add:before,.fa-plus:before{content:"\2b"}.fa-expand:before{content:"\f065"}.fa-computer:before{content:"\e4e5"}.fa-close:before,.fa-multiply:before,.fa-remove:before,.fa-times:before,.fa-xmark:before{content:"\f00d"}.fa-arrows-up-down-left-right:before,.fa-arrows:before{content:"\f047"}.fa-chalkboard-teacher:before,.fa-chalkboard-user:before{content:"\f51c"}.fa-peso-sign:before{content:"\e222"}.fa-building-shield:before{content:"\e4d8"}.fa-baby:before{content:"\f77c"}.fa-users-line:before{content:"\e592"}.fa-quote-left-alt:before,.fa-quote-left:before{content:"\f10d"}.fa-tractor:before{content:"\f722"}.fa-trash-arrow-up:before,.fa-trash-restore:before{content:"\f829"}.fa-arrow-down-up-lock:before{content:"\e4b0"}.fa-lines-leaning:before{content:"\e51e"}.fa-ruler-combined:before{content:"\f546"}.fa-copyright:before{content:"\f1f9"}.fa-equals:before{content:"\3d"}.fa-blender:before{content:"\f517"}.fa-teeth:before{content:"\f62e"}.fa-ils:before,.fa-shekel-sign:before,.fa-shekel:before,.fa-sheqel-sign:before,.fa-sheqel:before{content:"\f20b"}.fa-map:before{content:"\f279"}.fa-rocket:before{content:"\f135"}.fa-photo-film:before,.fa-photo-video:before{content:"\f87c"}.fa-folder-minus:before{content:"\f65d"}.fa-store:before{content:"\f54e"}.fa-arrow-trend-up:before{content:"\e098"}.fa-plug-circle-minus:before{content:"\e55e"}.fa-sign-hanging:before,.fa-sign:before{content:"\f4d9"}.fa-bezier-curve:before{content:"\f55b"}.fa-bell-slash:before{content:"\f1f6"}.fa-tablet-android:before,.fa-tablet:before{content:"\f3fb"}.fa-school-flag:before{content:"\e56e"}.fa-fill:before{content:"\f575"}.fa-angle-up:before{content:"\f106"}.fa-drumstick-bite:before{content:"\f6d7"}.fa-holly-berry:before{content:"\f7aa"}.fa-chevron-left:before{content:"\f053"}.fa-bacteria:before{content:"\e059"}.fa-hand-lizard:before{content:"\f258"}.fa-notdef:before{content:"\e1fe"}.fa-disease:before{content:"\f7fa"}.fa-briefcase-medical:before{content:"\f469"}.fa-genderless:before{content:"\f22d"}.fa-chevron-right:before{content:"\f054"}.fa-retweet:before{content:"\f079"}.fa-car-alt:before,.fa-car-rear:before{content:"\f5de"}.fa-pump-soap:before{content:"\e06b"}.fa-video-slash:before{content:"\f4e2"}.fa-battery-2:before,.fa-battery-quarter:before{content:"\f243"}.fa-radio:before{content:"\f8d7"}.fa-baby-carriage:before,.fa-carriage-baby:before{content:"\f77d"}.fa-traffic-light:before{content:"\f637"}.fa-thermometer:before{content:"\f491"}.fa-vr-cardboard:before{content:"\f729"}.fa-hand-middle-finger:before{content:"\f806"}.fa-percent:before,.fa-percentage:before{content:"\25"}.fa-truck-moving:before{content:"\f4df"}.fa-glass-water-droplet:before{content:"\e4f5"}.fa-display:before{content:"\e163"}.fa-face-smile:before,.fa-smile:before{content:"\f118"}.fa-thumb-tack:before,.fa-thumbtack:before{content:"\f08d"}.fa-trophy:before{content:"\f091"}.fa-person-praying:before,.fa-pray:before{content:"\f683"}.fa-hammer:before{content:"\f6e3"}.fa-hand-peace:before{content:"\f25b"}.fa-rotate:before,.fa-sync-alt:before{content:"\f2f1"}.fa-spinner:before{content:"\f110"}.fa-robot:before{content:"\f544"}.fa-peace:before{content:"\f67c"}.fa-cogs:before,.fa-gears:before{content:"\f085"}.fa-warehouse:before{content:"\f494"}.fa-arrow-up-right-dots:before{content:"\e4b7"}.fa-splotch:before{content:"\f5bc"}.fa-face-grin-hearts:before,.fa-grin-hearts:before{content:"\f584"}.fa-dice-four:before{content:"\f524"}.fa-sim-card:before{content:"\f7c4"}.fa-transgender-alt:before,.fa-transgender:before{content:"\f225"}.fa-mercury:before{content:"\f223"}.fa-arrow-turn-down:before,.fa-level-down:before{content:"\f149"}.fa-person-falling-burst:before{content:"\e547"}.fa-award:before{content:"\f559"}.fa-ticket-alt:before,.fa-ticket-simple:before{content:"\f3ff"}.fa-building:before{content:"\f1ad"}.fa-angle-double-left:before,.fa-angles-left:before{content:"\f100"}.fa-qrcode:before{content:"\f029"}.fa-clock-rotate-left:before,.fa-history:before{content:"\f1da"}.fa-face-grin-beam-sweat:before,.fa-grin-beam-sweat:before{content:"\f583"}.fa-arrow-right-from-file:before,.fa-file-export:before{content:"\f56e"}.fa-shield-blank:before,.fa-shield:before{content:"\f132"}.fa-arrow-up-short-wide:before,.fa-sort-amount-up-alt:before{content:"\f885"}.fa-house-medical:before{content:"\e3b2"}.fa-golf-ball-tee:before,.fa-golf-ball:before{content:"\f450"}.fa-chevron-circle-left:before,.fa-circle-chevron-left:before{content:"\f137"}.fa-house-chimney-window:before{content:"\e00d"}.fa-pen-nib:before{content:"\f5ad"}.fa-tent-arrow-turn-left:before{content:"\e580"}.fa-tents:before{content:"\e582"}.fa-magic:before,.fa-wand-magic:before{content:"\f0d0"}.fa-dog:before{content:"\f6d3"}.fa-carrot:before{content:"\f787"}.fa-moon:before{content:"\f186"}.fa-wine-glass-alt:before,.fa-wine-glass-empty:before{content:"\f5ce"}.fa-cheese:before{content:"\f7ef"}.fa-yin-yang:before{content:"\f6ad"}.fa-music:before{content:"\f001"}.fa-code-commit:before{content:"\f386"}.fa-temperature-low:before{content:"\f76b"}.fa-biking:before,.fa-person-biking:before{content:"\f84a"}.fa-broom:before{content:"\f51a"}.fa-shield-heart:before{content:"\e574"}.fa-gopuram:before{content:"\f664"}.fa-earth-oceania:before,.fa-globe-oceania:before{content:"\e47b"}.fa-square-xmark:before,.fa-times-square:before,.fa-xmark-square:before{content:"\f2d3"}.fa-hashtag:before{content:"\23"}.fa-expand-alt:before,.fa-up-right-and-down-left-from-center:before{content:"\f424"}.fa-oil-can:before{content:"\f613"}.fa-t:before{content:"\54"}.fa-hippo:before{content:"\f6ed"}.fa-chart-column:before{content:"\e0e3"}.fa-infinity:before{content:"\f534"}.fa-vial-circle-check:before{content:"\e596"}.fa-person-arrow-down-to-line:before{content:"\e538"}.fa-voicemail:before{content:"\f897"}.fa-fan:before{content:"\f863"}.fa-person-walking-luggage:before{content:"\e554"}.fa-arrows-alt-v:before,.fa-up-down:before{content:"\f338"}.fa-cloud-moon-rain:before{content:"\f73c"}.fa-calendar:before{content:"\f133"}.fa-trailer:before{content:"\e041"}.fa-bahai:before,.fa-haykal:before{content:"\f666"}.fa-sd-card:before{content:"\f7c2"}.fa-dragon:before{content:"\f6d5"}.fa-shoe-prints:before{content:"\f54b"}.fa-circle-plus:before,.fa-plus-circle:before{content:"\f055"}.fa-face-grin-tongue-wink:before,.fa-grin-tongue-wink:before{content:"\f58b"}.fa-hand-holding:before{content:"\f4bd"}.fa-plug-circle-exclamation:before{content:"\e55d"}.fa-chain-broken:before,.fa-chain-slash:before,.fa-link-slash:before,.fa-unlink:before{content:"\f127"}.fa-clone:before{content:"\f24d"}.fa-person-walking-arrow-loop-left:before{content:"\e551"}.fa-arrow-up-z-a:before,.fa-sort-alpha-up-alt:before{content:"\f882"}.fa-fire-alt:before,.fa-fire-flame-curved:before{content:"\f7e4"}.fa-tornado:before{content:"\f76f"}.fa-file-circle-plus:before{content:"\e494"}.fa-book-quran:before,.fa-quran:before{content:"\f687"}.fa-anchor:before{content:"\f13d"}.fa-border-all:before{content:"\f84c"}.fa-angry:before,.fa-face-angry:before{content:"\f556"}.fa-cookie-bite:before{content:"\f564"}.fa-arrow-trend-down:before{content:"\e097"}.fa-feed:before,.fa-rss:before{content:"\f09e"}.fa-draw-polygon:before{content:"\f5ee"}.fa-balance-scale:before,.fa-scale-balanced:before{content:"\f24e"}.fa-gauge-simple-high:before,.fa-tachometer-fast:before,.fa-tachometer:before{content:"\f62a"}.fa-shower:before{content:"\f2cc"}.fa-desktop-alt:before,.fa-desktop:before{content:"\f390"}.fa-m:before{content:"\4d"}.fa-table-list:before,.fa-th-list:before{content:"\f00b"}.fa-comment-sms:before,.fa-sms:before{content:"\f7cd"}.fa-book:before{content:"\f02d"}.fa-user-plus:before{content:"\f234"}.fa-check:before{content:"\f00c"}.fa-battery-4:before,.fa-battery-three-quarters:before{content:"\f241"}.fa-house-circle-check:before{content:"\e509"}.fa-angle-left:before{content:"\f104"}.fa-diagram-successor:before{content:"\e47a"}.fa-truck-arrow-right:before{content:"\e58b"}.fa-arrows-split-up-and-left:before{content:"\e4bc"}.fa-fist-raised:before,.fa-hand-fist:before{content:"\f6de"}.fa-cloud-moon:before{content:"\f6c3"}.fa-briefcase:before{content:"\f0b1"}.fa-person-falling:before{content:"\e546"}.fa-image-portrait:before,.fa-portrait:before{content:"\f3e0"}.fa-user-tag:before{content:"\f507"}.fa-rug:before{content:"\e569"}.fa-earth-europe:before,.fa-globe-europe:before{content:"\f7a2"}.fa-cart-flatbed-suitcase:before,.fa-luggage-cart:before{content:"\f59d"}.fa-rectangle-times:before,.fa-rectangle-xmark:before,.fa-times-rectangle:before,.fa-window-close:before{content:"\f410"}.fa-baht-sign:before{content:"\e0ac"}.fa-book-open:before{content:"\f518"}.fa-book-journal-whills:before,.fa-journal-whills:before{content:"\f66a"}.fa-handcuffs:before{content:"\e4f8"}.fa-exclamation-triangle:before,.fa-triangle-exclamation:before,.fa-warning:before{content:"\f071"}.fa-database:before{content:"\f1c0"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-bottle-droplet:before{content:"\e4c4"}.fa-mask-face:before{content:"\e1d7"}.fa-hill-rockslide:before{content:"\e508"}.fa-exchange-alt:before,.fa-right-left:before{content:"\f362"}.fa-paper-plane:before{content:"\f1d8"}.fa-road-circle-exclamation:before{content:"\e565"}.fa-dungeon:before{content:"\f6d9"}.fa-align-right:before{content:"\f038"}.fa-money-bill-1-wave:before,.fa-money-bill-wave-alt:before{content:"\f53b"}.fa-life-ring:before{content:"\f1cd"}.fa-hands:before,.fa-sign-language:before,.fa-signing:before{content:"\f2a7"}.fa-calendar-day:before{content:"\f783"}.fa-ladder-water:before,.fa-swimming-pool:before,.fa-water-ladder:before{content:"\f5c5"}.fa-arrows-up-down:before,.fa-arrows-v:before{content:"\f07d"}.fa-face-grimace:before,.fa-grimace:before{content:"\f57f"}.fa-wheelchair-alt:before,.fa-wheelchair-move:before{content:"\e2ce"}.fa-level-down-alt:before,.fa-turn-down:before{content:"\f3be"}.fa-person-walking-arrow-right:before{content:"\e552"}.fa-envelope-square:before,.fa-square-envelope:before{content:"\f199"}.fa-dice:before{content:"\f522"}.fa-bowling-ball:before{content:"\f436"}.fa-brain:before{content:"\f5dc"}.fa-band-aid:before,.fa-bandage:before{content:"\f462"}.fa-calendar-minus:before{content:"\f272"}.fa-circle-xmark:before,.fa-times-circle:before,.fa-xmark-circle:before{content:"\f057"}.fa-gifts:before{content:"\f79c"}.fa-hotel:before{content:"\f594"}.fa-earth-asia:before,.fa-globe-asia:before{content:"\f57e"}.fa-id-card-alt:before,.fa-id-card-clip:before{content:"\f47f"}.fa-magnifying-glass-plus:before,.fa-search-plus:before{content:"\f00e"}.fa-thumbs-up:before{content:"\f164"}.fa-user-clock:before{content:"\f4fd"}.fa-allergies:before,.fa-hand-dots:before{content:"\f461"}.fa-file-invoice:before{content:"\f570"}.fa-window-minimize:before{content:"\f2d1"}.fa-coffee:before,.fa-mug-saucer:before{content:"\f0f4"}.fa-brush:before{content:"\f55d"}.fa-mask:before{content:"\f6fa"}.fa-magnifying-glass-minus:before,.fa-search-minus:before{content:"\f010"}.fa-ruler-vertical:before{content:"\f548"}.fa-user-alt:before,.fa-user-large:before{content:"\f406"}.fa-train-tram:before{content:"\e5b4"}.fa-user-nurse:before{content:"\f82f"}.fa-syringe:before{content:"\f48e"}.fa-cloud-sun:before{content:"\f6c4"}.fa-stopwatch-20:before{content:"\e06f"}.fa-square-full:before{content:"\f45c"}.fa-magnet:before{content:"\f076"}.fa-jar:before{content:"\e516"}.fa-note-sticky:before,.fa-sticky-note:before{content:"\f249"}.fa-bug-slash:before{content:"\e490"}.fa-arrow-up-from-water-pump:before{content:"\e4b6"}.fa-bone:before{content:"\f5d7"}.fa-user-injured:before{content:"\f728"}.fa-face-sad-tear:before,.fa-sad-tear:before{content:"\f5b4"}.fa-plane:before{content:"\f072"}.fa-tent-arrows-down:before{content:"\e581"}.fa-exclamation:before{content:"\21"}.fa-arrows-spin:before{content:"\e4bb"}.fa-print:before{content:"\f02f"}.fa-try:before,.fa-turkish-lira-sign:before,.fa-turkish-lira:before{content:"\e2bb"}.fa-dollar-sign:before,.fa-dollar:before,.fa-usd:before{content:"\24"}.fa-x:before{content:"\58"}.fa-magnifying-glass-dollar:before,.fa-search-dollar:before{content:"\f688"}.fa-users-cog:before,.fa-users-gear:before{content:"\f509"}.fa-person-military-pointing:before{content:"\e54a"}.fa-bank:before,.fa-building-columns:before,.fa-institution:before,.fa-museum:before,.fa-university:before{content:"\f19c"}.fa-umbrella:before{content:"\f0e9"}.fa-trowel:before{content:"\e589"}.fa-d:before{content:"\44"}.fa-stapler:before{content:"\e5af"}.fa-masks-theater:before,.fa-theater-masks:before{content:"\f630"}.fa-kip-sign:before{content:"\e1c4"}.fa-hand-point-left:before{content:"\f0a5"}.fa-handshake-alt:before,.fa-handshake-simple:before{content:"\f4c6"}.fa-fighter-jet:before,.fa-jet-fighter:before{content:"\f0fb"}.fa-share-alt-square:before,.fa-square-share-nodes:before{content:"\f1e1"}.fa-barcode:before{content:"\f02a"}.fa-plus-minus:before{content:"\e43c"}.fa-video-camera:before,.fa-video:before{content:"\f03d"}.fa-graduation-cap:before,.fa-mortar-board:before{content:"\f19d"}.fa-hand-holding-medical:before{content:"\e05c"}.fa-person-circle-check:before{content:"\e53e"}.fa-level-up-alt:before,.fa-turn-up:before{content:"\f3bf"} +.fa-sr-only,.fa-sr-only-focusable:not(:focus),.sr-only,.sr-only-focusable:not(:focus){position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0} \ No newline at end of file diff --git a/css/solid.min.css b/css/solid.min.css new file mode 100644 index 00000000..7e1fb2d4 --- /dev/null +++ b/css/solid.min.css @@ -0,0 +1,6 @@ +/*! + * Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com + * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) + * Copyright 2023 Fonticons, Inc. + */ +:host,:root{--fa-style-family-classic:"Font Awesome 6 Free";--fa-font-solid:normal 900 1em/1 "Font Awesome 6 Free"}@font-face{font-family:"Font Awesome 6 Free";font-style:normal;font-weight:900;font-display:block;src:url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.ttf) format("truetype")}.fa-solid,.fas{font-weight:900} \ No newline at end of file diff --git a/css/v4-font-face.min.css b/css/v4-font-face.min.css new file mode 100644 index 00000000..dadd6c56 --- /dev/null +++ b/css/v4-font-face.min.css @@ -0,0 +1,6 @@ +/*! + * Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com + * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) + * Copyright 2023 Fonticons, Inc. + */ +@font-face{font-family:"FontAwesome";font-display:block;src:url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.ttf) format("truetype")}@font-face{font-family:"FontAwesome";font-display:block;src:url(../webfonts/fa-brands-400.woff2) format("woff2"),url(../webfonts/fa-brands-400.ttf) format("truetype")}@font-face{font-family:"FontAwesome";font-display:block;src:url(../webfonts/fa-regular-400.woff2) format("woff2"),url(../webfonts/fa-regular-400.ttf) format("truetype");unicode-range:u+f003,u+f006,u+f014,u+f016-f017,u+f01a-f01b,u+f01d,u+f022,u+f03e,u+f044,u+f046,u+f05c-f05d,u+f06e,u+f070,u+f087-f088,u+f08a,u+f094,u+f096-f097,u+f09d,u+f0a0,u+f0a2,u+f0a4-f0a7,u+f0c5,u+f0c7,u+f0e5-f0e6,u+f0eb,u+f0f6-f0f8,u+f10c,u+f114-f115,u+f118-f11a,u+f11c-f11d,u+f133,u+f147,u+f14e,u+f150-f152,u+f185-f186,u+f18e,u+f190-f192,u+f196,u+f1c1-f1c9,u+f1d9,u+f1db,u+f1e3,u+f1ea,u+f1f7,u+f1f9,u+f20a,u+f247-f248,u+f24a,u+f24d,u+f255-f25b,u+f25d,u+f271-f274,u+f278,u+f27b,u+f28c,u+f28e,u+f29c,u+f2b5,u+f2b7,u+f2ba,u+f2bc,u+f2be,u+f2c0-f2c1,u+f2c3,u+f2d0,u+f2d2,u+f2d4,u+f2dc}@font-face{font-family:"FontAwesome";font-display:block;src:url(../webfonts/fa-v4compatibility.woff2) format("woff2"),url(../webfonts/fa-v4compatibility.ttf) format("truetype");unicode-range:u+f041,u+f047,u+f065-f066,u+f07d-f07e,u+f080,u+f08b,u+f08e,u+f090,u+f09a,u+f0ac,u+f0ae,u+f0b2,u+f0d0,u+f0d6,u+f0e4,u+f0ec,u+f10a-f10b,u+f123,u+f13e,u+f148-f149,u+f14c,u+f156,u+f15e,u+f160-f161,u+f163,u+f175-f178,u+f195,u+f1f8,u+f219,u+f27a} \ No newline at end of file diff --git a/img/favicon.ico b/img/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..e85006a3ce1c6fd81faa6d5a13095519c4a6fc96 GIT binary patch literal 1150 zcmd6lF-yZh9L1kl>(HSEK`2y^4yB6->f+$wD)=oNY!UheIt03Q=;qj=;8*Bap_4*& za8yAl;wmmx5Yyi^7dXN-WYdJ-{qNqpcez|5t#Fr0qTSYcPTG`I2PBk8r$~4kg^0zN zCJe(rhix3do!L$bZ+IuZ{i08x=JR3=e+M4pv0KsKA??{u_*EFfo|`p&t`Vf=jn{)F z1fKk9hWsmYwqWAP^JO*5u*R;*L&dX3H$%S7oB$f0{ISh{QVXuncnzN67WQH2`lip7 zhX+VI$6x$1+$8gMjh4+1l0N#8_0Fh=N#EwpKk{SeE!)SHFB@xQFX3y+8sF#_@!bDW eIdI-IC`$c%>bk?KbPeN9RHtL<1^)v~#xMt8oB^@` literal 0 HcmV?d00001 diff --git a/img/grid.png b/img/grid.png new file mode 100644 index 0000000000000000000000000000000000000000..878c3ed5c196539c4e2da35b7787ab08e98b9cca GIT binary patch literal 1458 zcmeAS@N?(olHy`uVBq!ia0vp^Q49=>MjUKFR#nCEMj*vm;1OBOz`!jG!i)^F=12fl zLsS+C#C9D4%n8IWc}2f)ZEm(l45;BJwtuC;Xu7MDalsFrAb+- z$t7TS!;J%bz$r0ZA4%9oA5*oBKFCE#E`)d=EDH3$9hZ$hJS^?Fp4#&|GB7Z|@^o^SSJTd6tq0S!DeK!2h*Tl*`P5Yzc8-3Bx*#7*P z_lIZyDoaaS`}OwX=Dx>2?#BS1xgR(Q!d=p|X>EOCN` zXA4VQu*xH8*v`wH|7Kg_&!-n1cjuav&3^o%1B-!38l2qsw5vX{)ww9+?vCFTf>ud~ zg*GO3KC`e=!r@T3xzf`*c)d-IUlfFk;PBjy4K6tmi!A&4@cAEP$Px9s?lqTci7~T+ z-}^{4afY_30{uixxSHt*N>9t^Tda&0H5mQ_1`yCs#p`NH*8Km)_~-KFoNo=!_8c#s zWAa>N-HQ`bo%5fbxey)esBZQ2{nIXNu`Os-bmok|{*PU&?;Wq;K7ViC-rR_~+KOL= zH4)jidxUns0>)Izao*FaI~PF{%uT~Dk@j=8|5Dta{K8wv>d|%Hcb{Lgz3+r2sU6kg zmTAw9&-`i8w14I8wx>P5N6NF;+MlVs*O$JfT6WJou)_P>@A@uXTleG5F;Ur%rwkr} z9Cy=jOL!Yh{`u60)j+55f37_IN$UUe9sghL7uuB@5hwlYz5Q2Eoi? z8|G~6tcc3~n|batFcfpX-rfHA^NYK3=QY>WxaPaUGs?d6cXxkJIsW|O^e4z^d}6ZQ z{XhH5lWzwfnEw0KbC6*c*P{6UH^(HL+Z_Lz)%(e&^e>X(pJ#64-W$DObB_40RoL^? hufEOi_HxMn + + + + + + + + + + RomWBW Documentation V3.6 + + + + + + + + + + + + + + + + +
+
+
+
+ +

$define{doc_title}{ReadMe}$ +$include{"Basic.h"}$

+

Overview

+

RomWBW software provides a complete, commercial quality +implementation of CP/M (and workalike) operating systems and +applications for modern Z80/180/280 retro-computing hardware systems.

+

A wide variety of platforms are supported including those +produced by these developer communities:

+ +

A complete list of the currently supported platforms is found in the +[Installation] section.

+

Supported hardware features of RomWBW include:

+
    +
  • Z80 Family CPUs including Z80, Z180, and Z280
  • +
  • Banked memory services for several banking designs
  • +
  • Disk drivers for RAM, ROM, Floppy, IDE ATA/ATAPI, CF, SD, USB, Zip, Iomega
  • +
  • Serial drivers including UART (16550-like), ASCI, ACIA, SIO
  • +
  • Video drivers including TMS9918, SY6545, MOS8563, HD6445
  • +
  • Keyboard (PS/2) drivers via VT8242 or PPI interfaces
  • +
  • Real time clock drivers including DS1302, BQ4845
  • +
  • Support for CP/NET networking using Wiznet, MT011 or Serial
  • +
  • Built-in VT-100 terminal emulation support
  • +
+

RomWBW is distributed as both source code and pre-built ROM and disk +images. Some of the provided software can be launched directly from the +ROM firmware itself:

+
    +
  • System Monitor
  • +
  • Operating Systems (CP/M 2.2, ZSDOS)
  • +
  • ROM BASIC (Nascom BASIC and Tasty BASIC)
  • +
  • ROM Forth
  • +
+

A dynamic disk drive letter assignment mechanism allows mapping +operating system drive letters to any available disk media. +Additionally, mass storage devices (IDE Disk, CF Card, SD Card, etc.) +support the use of multiple slices (up to 256 per device). Each slice +contains a complete CP/M filesystem and can be mapped independently to +any drive letter. This overcomes the inherent size limitations in legacy +OSes and allows up to 2GB of accessible storage on a single device, +with up to 128MB accessible at any one time.

+

The pre-built ROM firmware images are generally suitable for most +users. However, it is also very easy to modify and build custom ROM +images that fully tailor the firmware to your specific preferences. +All tools required to build custom ROM firmware under Windows are +included -- no need to install assemblers, etc. The firmware can also +be built using Linux or MacOS after confirming a few standard tools +have been installed.

+

Multiple disk images are provided in the distribution. Most disk +images contain a complete, bootable, ready-to-run implementation of a +specific operating system. A "combo" disk image contains multiple +slices, each with a full operating system implementation. If you use +this disk image, you can easily pick whichever operating system you +want to boot without changing media.

+

By design, RomWBW isolates all of the hardware specific functions in +the ROM chip itself. The ROM provides a hardware abstraction layer +such that all of the operating systems and applications on a disk +will run on any RomWBW-based system. To put it simply, you can take +a disk (or CF/SD/USB Card) and move it between systems transparently.

+

A tool is provided that allows you to access a FAT-12/16/32 filesystem. +The FAT filesystem may be coresident on the same disk media as RomWBW +slices or on stand-alone media. This makes exchanging files with modern +OSes such as Windows, MacOS, and Linux very easy.

+

Acquiring RomWBW

+

The RomWBW Repository +(https://github.com/wwarthen/RomWBW) on GitHub is the official +distribution location for all project source and documentation. +The fully-built distribution releases are available on the +RomWBW Releases Page +(https://github.com/wwarthen/RomWBW/releases) of the repository. +On this page, you will normally see a Development Snapshot as well as +recent stable releases. Unless you have a specific reason, I suggest you +stick to the most recent stable release.

+

The asset named RomWBW-vX.X.X-Package.zip includes all pre-built ROM +and Disk images as well as full source code. The other assets contain +only source code and do not have the pre-built ROM or disk images.

+

All source code and distributions are maintained on GitHub. Code +contributions are very welcome.

+

Installation & Operation

+

In general, installation of RomWBW on your platform is very simple. You +just need to program your ROM with the correct ROM image from the RomWBW +distribution. Subsequently, you can write disk images on your disk +drives (IDE disk, CF Card, SD Card, etc.) which then provides even more +functionality.

+

Complete instructions for installation and operation of RomWBW are +found in the $doc_user$. It is also a good idea to review the +Release Notes +for helpful release-specific information.

+

Documentation

+

Documentation for $doc_product$ includes:

+
    +
  • $doc_intro$
  • +
  • $doc_user$
  • +
  • $doc_sys$
  • +
  • $doc_apps$
  • +
  • $doc_catalog$
  • +
  • $doc_hardware$
  • +
+

Acknowledgments

+

I want to acknowledge that a great deal of the code and inspiration +for RomWBW has been provided by or derived from the work of others +in the RetroBrew Computers Community. I sincerely appreciate all of +their contributions. The list below is probably missing many names -- +please let me know if I missed you!

+
    +
  • +

    Andrew Lynch started it all when he created the N8VEM Z80 SBC + which became the first platform RomWBW supported. Some of his + original code can still be found in RomWBW.

    +
  • +
  • +

    Dan Werner wrote much of the code from which RomWBW was originally + derived and he has always been a great source of knowledge and + advice.

    +
  • +
  • +

    Douglas Goodall contributed code, time, testing, and advice in "the + early days". He created an entire suite of application programs to + enhance the use of RomWBW. Unfortunately, they have become unusable + due to internal changes within RomWBW. As of RomWBW 2.6, these + applications are no longer provided.

    +
  • +
  • +

    Sergey Kiselev created several hardware platforms for RomWBW + including the very popular Zeta.

    +
  • +
  • +

    David Giles created support for the Z180 CSIO which is now included + SD Card driver.

    +
  • +
  • +

    Phil Summers contributed the Forth and BASIC adaptations in ROM, the + AY-3-8910 sound driver, DMA support, and a long list of general code + and documentation enhancements.

    +
  • +
  • +

    Ed Brindley contributed some of the code that supports the RCBus + platform.

    +
  • +
  • +

    Spencer Owen created the RC2014 series of hobbyist kit computers + which has exponentially increased RomWBW usage. Some of his kits + include RomWBW.

    +
  • +
  • +

    Stephen Cousins has likewise created a series of hobbyist kit + computers at Small Computer Central and is distributing RomWBW + with many of them.

    +
  • +
  • +

    Alan Cox has contributed some driver code and has provided a great + deal of advice.

    +
  • +
  • +

    The CP/NET client files were developed by Douglas Miller.

    +
  • +
  • +

    Phillip Stevens contributed support for FreeRTOS.

    +
  • +
  • +

    Curt Mayer contributed the original Linux / MacOS build process.

    +
  • +
  • +

    UNA BIOS and FDISK80 are the products of John Coffman.

    +
  • +
  • +

    FLASH4 is a product of Will Sowerbutts.

    +
  • +
  • +

    CLRDIR is a product of Max Scane.

    +
  • +
  • +

    Tasty Basic is a product of Dimitri Theulings.

    +
  • +
  • +

    Dean Netherton contributed eZ80 CPU support, the sound driver + interface, and the SN76489 sound driver.

    +
  • +
  • +

    The RomWBW Disk Catalog document was produced by Mykl Orders.

    +
  • +
  • +

    Rob Prouse has created many of the supplemental disk images + including Aztec C, HiTech C, SLR Z80ASM, Turbo Pascal, Microsoft + BASIC Compiler, Microsoft Fortran Compiler, and a Games + compendium.

    +
  • +
  • +

    Martin R has provided substantial help reviewing and improving the + User Guide and Applications documents.

    +
  • +
  • +

    Mark Pruden has made a wide variety of contributions including:

    +
  • +
  • significant content in the Disk Catalog and User Guide
  • +
  • creation of the Introduction and Hardware documents
  • +
  • Z3PLUS operating system disk image
  • +
  • COPYSL and SLABEL utility
  • +
  • a feature for RomWBW configuration by NVRAM
  • +
  • +

    the /B bulk mode of disk assignment to the ASSIGN utility

    +
  • +
  • +

    Jacques Pelletier has contributed the DS1501 RTC driver code.

    +
  • +
  • +

    Jose Collado has contributed enhancements to the TMS driver + including compatibility with standard TMS register configuration.

    +
  • +
  • +

    Kevin Boone has contributed a generic HBIOS date/time utility (WDATE).

    +
  • +
  • +

    Matt Carroll has contributed a fix to XM.COM that corrects the + port specification when doing a send.

    +
  • +
  • +

    Dean Jenkins enhanced the build process to accommodate the + Raspberry Pi 4.

    +
  • +
  • +

    Tom Plano has contributed a new utility (HTALK) to allow talking + directly to HBIOS COM ports.

    +
  • +
  • +

    Lars Nelson has contributed several generic utilities such as + a universal (OS agnostic) UNARC application.

    +
  • +
  • +

    Dylan Hall added support for specifying a secondary console.

    +
  • +
  • +

    Bill Shen has contributed boot loaders for several of his + systems.

    +
  • +
  • +

    Laszlo Szolnoki has contributed an EF9345 video display + controller driver.

    +
  • +
  • +

    Ladislau Szilagyi has contributed an enhanced version of + CP/M Cowgol that leverages RomWBW memory banking.

    +
  • +
  • +

    Les Bird has contributed support for the NABU w/ Option Board

    +
  • +
+

Contributions of all kinds to RomWBW are very welcome.

+

Licensing

+

RomWBW is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version.

+

RomWBW is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details.

+

You should have received a copy of the GNU General Public License +along with RomWBW. If not, see https://www.gnu.org/licenses/.

+

Portions of RomWBW were created by, contributed by, or derived from +the work of others. It is believed that these works are being used +in accordance with the intentions and/or licensing of their creators.

+

If anyone feels their work is being used outside of its intended +licensing, please notify:

+
+

$doc_author$ \ +$doc_authmail$

+
+

RomWBW is an aggregate work. It is composed of many individual, +standalone programs that are distributed as a whole to function as +a cohesive system. Each program may have its own licensing which +may be different from other programs within the aggregate.

+

In some cases, a single program (e.g., CP/M Operating System) is +composed of multiple components with different licenses. It is +believed that in all such cases the licenses are compatible with +GPL version 3.

+

RomWBW encourages code contributions from others. Contributors +may assert their own copyright in their contributions by +annotating the contributed source code appropriately. Contributors +are further encouraged to submit their contributions via the RomWBW +source code control system to ensure their contributions are clearly +documented.

+

All contributions to RomWBW are subject to this license.

+

Getting Assistance

+

The best way to get assistance with RomWBW or any aspect of the +RetroBrew Computers projects is via one of the community forums:

+ +

Submission of issues and bugs are welcome at the +RomWBW GitHub Repository.

+

Also feel free to email $doc_author$ at $doc_authmail$.

+
+
+ +
+
+

Documentation built with MkDocs.

+
+ + + + + + + + + + + diff --git a/js/base.js b/js/base.js new file mode 100644 index 00000000..957ccad1 --- /dev/null +++ b/js/base.js @@ -0,0 +1,287 @@ +function getSearchTerm() { + var sPageURL = window.location.search.substring(1); + var sURLVariables = sPageURL.split('&'); + for (var i = 0; i < sURLVariables.length; i++) { + var sParameterName = sURLVariables[i].split('='); + if (sParameterName[0] == 'q') { + return sParameterName[1]; + } + } +} + +function applyTopPadding() { + // Update various absolute positions to match where the main container + // starts. This is necessary for handling multi-line nav headers, since + // that pushes the main container down. + var container = document.querySelector('body > .container'); + var offset = container.offsetTop; + + document.documentElement.style.scrollPaddingTop = offset + 'px'; + document.querySelectorAll('.bs-sidebar.affix').forEach(function(sidebar) { + sidebar.style.top = offset + 'px'; + }); +} + +document.addEventListener("DOMContentLoaded", function () { + var search_term = getSearchTerm(); + var search_modal = new bootstrap.Modal(document.getElementById('mkdocs_search_modal')); + var keyboard_modal = new bootstrap.Modal(document.getElementById('mkdocs_keyboard_modal')); + + if (search_term) { + search_modal.show(); + } + + // make sure search input gets autofocus every time modal opens. + document.getElementById('mkdocs_search_modal').addEventListener('shown.bs.modal', function() { + document.getElementById('mkdocs-search-query').focus(); + }); + + // Close search modal when result is selected + // The links get added later so listen to parent + document.getElementById('mkdocs-search-results').addEventListener('click', function(e) { + if (e.target.tagName === 'A') { + search_modal.hide(); + } + }); + + // Populate keyboard modal with proper Keys + document.querySelector('.help.shortcut kbd').innerHTML = keyCodes[shortcuts.help]; + document.querySelector('.prev.shortcut kbd').innerHTML = keyCodes[shortcuts.previous]; + document.querySelector('.next.shortcut kbd').innerHTML = keyCodes[shortcuts.next]; + document.querySelector('.search.shortcut kbd').innerHTML = keyCodes[shortcuts.search]; + + // Keyboard navigation + document.addEventListener("keydown", function(e) { + if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA') return true; + var key = e.which || e.keyCode || window.event && window.event.keyCode; + var page; + switch (key) { + case shortcuts.next: + page = document.querySelector('.navbar a[rel="next"]'); + break; + case shortcuts.previous: + page = document.querySelector('.navbar a[rel="prev"]'); + break; + case shortcuts.search: + e.preventDefault(); + keyboard_modal.hide(); + search_modal.show(); + document.getElementById('mkdocs-search-query').focus(); + break; + case shortcuts.help: + search_modal.hide(); + keyboard_modal.show(); + break; + default: break; + } + if (page && page.hasAttribute('href')) { + keyboard_modal.hide(); + window.location.href = page.getAttribute('href'); + } + }); + + document.querySelectorAll('table').forEach(function(table) { + table.classList.add('table', 'table-striped', 'table-hover'); + }); + + function showInnerDropdown(item) { + var popup = item.nextElementSibling; + popup.classList.add('show'); + item.classList.add('open'); + + // First, close any sibling dropdowns. + var container = item.parentElement.parentElement; + container.querySelectorAll(':scope > .dropdown-submenu > a').forEach(function(el) { + if (el !== item) { + hideInnerDropdown(el); + } + }); + + var popupMargin = 10; + var maxBottom = window.innerHeight - popupMargin; + var bounds = item.getBoundingClientRect(); + + popup.style.left = bounds.right + 'px'; + if (bounds.top + popup.clientHeight > maxBottom && + bounds.top > window.innerHeight / 2) { + popup.style.top = (bounds.bottom - popup.clientHeight) + 'px'; + popup.style.maxHeight = (bounds.bottom - popupMargin) + 'px'; + } else { + popup.style.top = bounds.top + 'px'; + popup.style.maxHeight = (maxBottom - bounds.top) + 'px'; + } + } + + function hideInnerDropdown(item) { + var popup = item.nextElementSibling; + popup.classList.remove('show'); + item.classList.remove('open'); + + popup.scrollTop = 0; + var menu = popup.querySelector('.dropdown-menu'); + if (menu) { + menu.scrollTop = 0; + } + var dropdown = popup.querySelector('.dropdown-submenu > a'); + if (dropdown) { + dropdown.classList.remove('open'); + } + } + + document.querySelectorAll('.dropdown-submenu > a').forEach(function(item) { + item.addEventListener('click', function(e) { + if (item.nextElementSibling.classList.contains('show')) { + hideInnerDropdown(item); + } else { + showInnerDropdown(item); + } + + e.stopPropagation(); + e.preventDefault(); + }); + }); + + document.querySelectorAll('.dropdown-menu').forEach(function(menu) { + menu.parentElement.addEventListener('hide.bs.dropdown', function() { + menu.scrollTop = 0; + var dropdown = menu.querySelector('.dropdown-submenu > a'); + if (dropdown) { + dropdown.classList.remove('open'); + } + menu.querySelectorAll('.dropdown-menu .dropdown-menu').forEach(function(submenu) { + submenu.classList.remove('show'); + }); + }); + }); + + applyTopPadding(); +}); + +window.addEventListener('resize', applyTopPadding); + +var scrollSpy = new bootstrap.ScrollSpy(document.body, { + target: '.bs-sidebar' +}); + +/* Prevent disabled links from causing a page reload */ +document.querySelectorAll("li.disabled a").forEach(function(item) { + item.addEventListener("click", function(event) { + event.preventDefault(); + }); +}); + +// See https://www.cambiaresearch.com/articles/15/javascript-char-codes-key-codes +// We only list common keys below. Obscure keys are omitted and their use is discouraged. +var keyCodes = { + 8: 'backspace', + 9: 'tab', + 13: 'enter', + 16: 'shift', + 17: 'ctrl', + 18: 'alt', + 19: 'pause/break', + 20: 'caps lock', + 27: 'escape', + 32: 'spacebar', + 33: 'page up', + 34: 'page down', + 35: 'end', + 36: 'home', + 37: '←', + 38: '↑', + 39: '→', + 40: '↓', + 45: 'insert', + 46: 'delete', + 48: '0', + 49: '1', + 50: '2', + 51: '3', + 52: '4', + 53: '5', + 54: '6', + 55: '7', + 56: '8', + 57: '9', + 65: 'a', + 66: 'b', + 67: 'c', + 68: 'd', + 69: 'e', + 70: 'f', + 71: 'g', + 72: 'h', + 73: 'i', + 74: 'j', + 75: 'k', + 76: 'l', + 77: 'm', + 78: 'n', + 79: 'o', + 80: 'p', + 81: 'q', + 82: 'r', + 83: 's', + 84: 't', + 85: 'u', + 86: 'v', + 87: 'w', + 88: 'x', + 89: 'y', + 90: 'z', + 91: 'Left Windows Key / Left ⌘', + 92: 'Right Windows Key', + 93: 'Windows Menu / Right ⌘', + 96: 'numpad 0', + 97: 'numpad 1', + 98: 'numpad 2', + 99: 'numpad 3', + 100: 'numpad 4', + 101: 'numpad 5', + 102: 'numpad 6', + 103: 'numpad 7', + 104: 'numpad 8', + 105: 'numpad 9', + 106: 'multiply', + 107: 'add', + 109: 'subtract', + 110: 'decimal point', + 111: 'divide', + 112: 'f1', + 113: 'f2', + 114: 'f3', + 115: 'f4', + 116: 'f5', + 117: 'f6', + 118: 'f7', + 119: 'f8', + 120: 'f9', + 121: 'f10', + 122: 'f11', + 123: 'f12', + 124: 'f13', + 125: 'f14', + 126: 'f15', + 127: 'f16', + 128: 'f17', + 129: 'f18', + 130: 'f19', + 131: 'f20', + 132: 'f21', + 133: 'f22', + 134: 'f23', + 135: 'f24', + 144: 'num lock', + 145: 'scroll lock', + 186: ';', + 187: '=', + 188: ',', + 189: '‐', + 190: '.', + 191: '?', + 192: '`', + 219: '[', + 220: '\', + 221: ']', + 222: ''', +}; diff --git a/js/bootstrap.bundle.min.js b/js/bootstrap.bundle.min.js new file mode 100644 index 00000000..b1999d9a --- /dev/null +++ b/js/bootstrap.bundle.min.js @@ -0,0 +1,7 @@ +/*! + * Bootstrap v5.3.2 (https://getbootstrap.com/) + * Copyright 2011-2023 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + */ +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).bootstrap=e()}(this,(function(){"use strict";const t=new Map,e={set(e,i,n){t.has(e)||t.set(e,new Map);const s=t.get(e);s.has(i)||0===s.size?s.set(i,n):console.error(`Bootstrap doesn't allow more than one instance per element. Bound instance: ${Array.from(s.keys())[0]}.`)},get:(e,i)=>t.has(e)&&t.get(e).get(i)||null,remove(e,i){if(!t.has(e))return;const n=t.get(e);n.delete(i),0===n.size&&t.delete(e)}},i="transitionend",n=t=>(t&&window.CSS&&window.CSS.escape&&(t=t.replace(/#([^\s"#']+)/g,((t,e)=>`#${CSS.escape(e)}`))),t),s=t=>{t.dispatchEvent(new Event(i))},o=t=>!(!t||"object"!=typeof t)&&(void 0!==t.jquery&&(t=t[0]),void 0!==t.nodeType),r=t=>o(t)?t.jquery?t[0]:t:"string"==typeof t&&t.length>0?document.querySelector(n(t)):null,a=t=>{if(!o(t)||0===t.getClientRects().length)return!1;const e="visible"===getComputedStyle(t).getPropertyValue("visibility"),i=t.closest("details:not([open])");if(!i)return e;if(i!==t){const e=t.closest("summary");if(e&&e.parentNode!==i)return!1;if(null===e)return!1}return e},l=t=>!t||t.nodeType!==Node.ELEMENT_NODE||!!t.classList.contains("disabled")||(void 0!==t.disabled?t.disabled:t.hasAttribute("disabled")&&"false"!==t.getAttribute("disabled")),c=t=>{if(!document.documentElement.attachShadow)return null;if("function"==typeof t.getRootNode){const e=t.getRootNode();return e instanceof ShadowRoot?e:null}return t instanceof ShadowRoot?t:t.parentNode?c(t.parentNode):null},h=()=>{},d=t=>{t.offsetHeight},u=()=>window.jQuery&&!document.body.hasAttribute("data-bs-no-jquery")?window.jQuery:null,f=[],p=()=>"rtl"===document.documentElement.dir,m=t=>{var e;e=()=>{const e=u();if(e){const i=t.NAME,n=e.fn[i];e.fn[i]=t.jQueryInterface,e.fn[i].Constructor=t,e.fn[i].noConflict=()=>(e.fn[i]=n,t.jQueryInterface)}},"loading"===document.readyState?(f.length||document.addEventListener("DOMContentLoaded",(()=>{for(const t of f)t()})),f.push(e)):e()},g=(t,e=[],i=t)=>"function"==typeof t?t(...e):i,_=(t,e,n=!0)=>{if(!n)return void g(t);const o=(t=>{if(!t)return 0;let{transitionDuration:e,transitionDelay:i}=window.getComputedStyle(t);const n=Number.parseFloat(e),s=Number.parseFloat(i);return n||s?(e=e.split(",")[0],i=i.split(",")[0],1e3*(Number.parseFloat(e)+Number.parseFloat(i))):0})(e)+5;let r=!1;const a=({target:n})=>{n===e&&(r=!0,e.removeEventListener(i,a),g(t))};e.addEventListener(i,a),setTimeout((()=>{r||s(e)}),o)},b=(t,e,i,n)=>{const s=t.length;let o=t.indexOf(e);return-1===o?!i&&n?t[s-1]:t[0]:(o+=i?1:-1,n&&(o=(o+s)%s),t[Math.max(0,Math.min(o,s-1))])},v=/[^.]*(?=\..*)\.|.*/,y=/\..*/,w=/::\d+$/,A={};let E=1;const T={mouseenter:"mouseover",mouseleave:"mouseout"},C=new Set(["click","dblclick","mouseup","mousedown","contextmenu","mousewheel","DOMMouseScroll","mouseover","mouseout","mousemove","selectstart","selectend","keydown","keypress","keyup","orientationchange","touchstart","touchmove","touchend","touchcancel","pointerdown","pointermove","pointerup","pointerleave","pointercancel","gesturestart","gesturechange","gestureend","focus","blur","change","reset","select","submit","focusin","focusout","load","unload","beforeunload","resize","move","DOMContentLoaded","readystatechange","error","abort","scroll"]);function O(t,e){return e&&`${e}::${E++}`||t.uidEvent||E++}function x(t){const e=O(t);return t.uidEvent=e,A[e]=A[e]||{},A[e]}function k(t,e,i=null){return Object.values(t).find((t=>t.callable===e&&t.delegationSelector===i))}function L(t,e,i){const n="string"==typeof e,s=n?i:e||i;let o=I(t);return C.has(o)||(o=t),[n,s,o]}function S(t,e,i,n,s){if("string"!=typeof e||!t)return;let[o,r,a]=L(e,i,n);if(e in T){const t=t=>function(e){if(!e.relatedTarget||e.relatedTarget!==e.delegateTarget&&!e.delegateTarget.contains(e.relatedTarget))return t.call(this,e)};r=t(r)}const l=x(t),c=l[a]||(l[a]={}),h=k(c,r,o?i:null);if(h)return void(h.oneOff=h.oneOff&&s);const d=O(r,e.replace(v,"")),u=o?function(t,e,i){return function n(s){const o=t.querySelectorAll(e);for(let{target:r}=s;r&&r!==this;r=r.parentNode)for(const a of o)if(a===r)return P(s,{delegateTarget:r}),n.oneOff&&N.off(t,s.type,e,i),i.apply(r,[s])}}(t,i,r):function(t,e){return function i(n){return P(n,{delegateTarget:t}),i.oneOff&&N.off(t,n.type,e),e.apply(t,[n])}}(t,r);u.delegationSelector=o?i:null,u.callable=r,u.oneOff=s,u.uidEvent=d,c[d]=u,t.addEventListener(a,u,o)}function D(t,e,i,n,s){const o=k(e[i],n,s);o&&(t.removeEventListener(i,o,Boolean(s)),delete e[i][o.uidEvent])}function $(t,e,i,n){const s=e[i]||{};for(const[o,r]of Object.entries(s))o.includes(n)&&D(t,e,i,r.callable,r.delegationSelector)}function I(t){return t=t.replace(y,""),T[t]||t}const N={on(t,e,i,n){S(t,e,i,n,!1)},one(t,e,i,n){S(t,e,i,n,!0)},off(t,e,i,n){if("string"!=typeof e||!t)return;const[s,o,r]=L(e,i,n),a=r!==e,l=x(t),c=l[r]||{},h=e.startsWith(".");if(void 0===o){if(h)for(const i of Object.keys(l))$(t,l,i,e.slice(1));for(const[i,n]of Object.entries(c)){const s=i.replace(w,"");a&&!e.includes(s)||D(t,l,r,n.callable,n.delegationSelector)}}else{if(!Object.keys(c).length)return;D(t,l,r,o,s?i:null)}},trigger(t,e,i){if("string"!=typeof e||!t)return null;const n=u();let s=null,o=!0,r=!0,a=!1;e!==I(e)&&n&&(s=n.Event(e,i),n(t).trigger(s),o=!s.isPropagationStopped(),r=!s.isImmediatePropagationStopped(),a=s.isDefaultPrevented());const l=P(new Event(e,{bubbles:o,cancelable:!0}),i);return a&&l.preventDefault(),r&&t.dispatchEvent(l),l.defaultPrevented&&s&&s.preventDefault(),l}};function P(t,e={}){for(const[i,n]of Object.entries(e))try{t[i]=n}catch(e){Object.defineProperty(t,i,{configurable:!0,get:()=>n})}return t}function M(t){if("true"===t)return!0;if("false"===t)return!1;if(t===Number(t).toString())return Number(t);if(""===t||"null"===t)return null;if("string"!=typeof t)return t;try{return JSON.parse(decodeURIComponent(t))}catch(e){return t}}function j(t){return t.replace(/[A-Z]/g,(t=>`-${t.toLowerCase()}`))}const F={setDataAttribute(t,e,i){t.setAttribute(`data-bs-${j(e)}`,i)},removeDataAttribute(t,e){t.removeAttribute(`data-bs-${j(e)}`)},getDataAttributes(t){if(!t)return{};const e={},i=Object.keys(t.dataset).filter((t=>t.startsWith("bs")&&!t.startsWith("bsConfig")));for(const n of i){let i=n.replace(/^bs/,"");i=i.charAt(0).toLowerCase()+i.slice(1,i.length),e[i]=M(t.dataset[n])}return e},getDataAttribute:(t,e)=>M(t.getAttribute(`data-bs-${j(e)}`))};class H{static get Default(){return{}}static get DefaultType(){return{}}static get NAME(){throw new Error('You have to implement the static method "NAME", for each component!')}_getConfig(t){return t=this._mergeConfigObj(t),t=this._configAfterMerge(t),this._typeCheckConfig(t),t}_configAfterMerge(t){return t}_mergeConfigObj(t,e){const i=o(e)?F.getDataAttribute(e,"config"):{};return{...this.constructor.Default,..."object"==typeof i?i:{},...o(e)?F.getDataAttributes(e):{},..."object"==typeof t?t:{}}}_typeCheckConfig(t,e=this.constructor.DefaultType){for(const[n,s]of Object.entries(e)){const e=t[n],r=o(e)?"element":null==(i=e)?`${i}`:Object.prototype.toString.call(i).match(/\s([a-z]+)/i)[1].toLowerCase();if(!new RegExp(s).test(r))throw new TypeError(`${this.constructor.NAME.toUpperCase()}: Option "${n}" provided type "${r}" but expected type "${s}".`)}var i}}class W extends H{constructor(t,i){super(),(t=r(t))&&(this._element=t,this._config=this._getConfig(i),e.set(this._element,this.constructor.DATA_KEY,this))}dispose(){e.remove(this._element,this.constructor.DATA_KEY),N.off(this._element,this.constructor.EVENT_KEY);for(const t of Object.getOwnPropertyNames(this))this[t]=null}_queueCallback(t,e,i=!0){_(t,e,i)}_getConfig(t){return t=this._mergeConfigObj(t,this._element),t=this._configAfterMerge(t),this._typeCheckConfig(t),t}static getInstance(t){return e.get(r(t),this.DATA_KEY)}static getOrCreateInstance(t,e={}){return this.getInstance(t)||new this(t,"object"==typeof e?e:null)}static get VERSION(){return"5.3.2"}static get DATA_KEY(){return`bs.${this.NAME}`}static get EVENT_KEY(){return`.${this.DATA_KEY}`}static eventName(t){return`${t}${this.EVENT_KEY}`}}const B=t=>{let e=t.getAttribute("data-bs-target");if(!e||"#"===e){let i=t.getAttribute("href");if(!i||!i.includes("#")&&!i.startsWith("."))return null;i.includes("#")&&!i.startsWith("#")&&(i=`#${i.split("#")[1]}`),e=i&&"#"!==i?n(i.trim()):null}return e},z={find:(t,e=document.documentElement)=>[].concat(...Element.prototype.querySelectorAll.call(e,t)),findOne:(t,e=document.documentElement)=>Element.prototype.querySelector.call(e,t),children:(t,e)=>[].concat(...t.children).filter((t=>t.matches(e))),parents(t,e){const i=[];let n=t.parentNode.closest(e);for(;n;)i.push(n),n=n.parentNode.closest(e);return i},prev(t,e){let i=t.previousElementSibling;for(;i;){if(i.matches(e))return[i];i=i.previousElementSibling}return[]},next(t,e){let i=t.nextElementSibling;for(;i;){if(i.matches(e))return[i];i=i.nextElementSibling}return[]},focusableChildren(t){const e=["a","button","input","textarea","select","details","[tabindex]",'[contenteditable="true"]'].map((t=>`${t}:not([tabindex^="-"])`)).join(",");return this.find(e,t).filter((t=>!l(t)&&a(t)))},getSelectorFromElement(t){const e=B(t);return e&&z.findOne(e)?e:null},getElementFromSelector(t){const e=B(t);return e?z.findOne(e):null},getMultipleElementsFromSelector(t){const e=B(t);return e?z.find(e):[]}},R=(t,e="hide")=>{const i=`click.dismiss${t.EVENT_KEY}`,n=t.NAME;N.on(document,i,`[data-bs-dismiss="${n}"]`,(function(i){if(["A","AREA"].includes(this.tagName)&&i.preventDefault(),l(this))return;const s=z.getElementFromSelector(this)||this.closest(`.${n}`);t.getOrCreateInstance(s)[e]()}))},q=".bs.alert",V=`close${q}`,K=`closed${q}`;class Q extends W{static get NAME(){return"alert"}close(){if(N.trigger(this._element,V).defaultPrevented)return;this._element.classList.remove("show");const t=this._element.classList.contains("fade");this._queueCallback((()=>this._destroyElement()),this._element,t)}_destroyElement(){this._element.remove(),N.trigger(this._element,K),this.dispose()}static jQueryInterface(t){return this.each((function(){const e=Q.getOrCreateInstance(this);if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t](this)}}))}}R(Q,"close"),m(Q);const X='[data-bs-toggle="button"]';class Y extends W{static get NAME(){return"button"}toggle(){this._element.setAttribute("aria-pressed",this._element.classList.toggle("active"))}static jQueryInterface(t){return this.each((function(){const e=Y.getOrCreateInstance(this);"toggle"===t&&e[t]()}))}}N.on(document,"click.bs.button.data-api",X,(t=>{t.preventDefault();const e=t.target.closest(X);Y.getOrCreateInstance(e).toggle()})),m(Y);const U=".bs.swipe",G=`touchstart${U}`,J=`touchmove${U}`,Z=`touchend${U}`,tt=`pointerdown${U}`,et=`pointerup${U}`,it={endCallback:null,leftCallback:null,rightCallback:null},nt={endCallback:"(function|null)",leftCallback:"(function|null)",rightCallback:"(function|null)"};class st extends H{constructor(t,e){super(),this._element=t,t&&st.isSupported()&&(this._config=this._getConfig(e),this._deltaX=0,this._supportPointerEvents=Boolean(window.PointerEvent),this._initEvents())}static get Default(){return it}static get DefaultType(){return nt}static get NAME(){return"swipe"}dispose(){N.off(this._element,U)}_start(t){this._supportPointerEvents?this._eventIsPointerPenTouch(t)&&(this._deltaX=t.clientX):this._deltaX=t.touches[0].clientX}_end(t){this._eventIsPointerPenTouch(t)&&(this._deltaX=t.clientX-this._deltaX),this._handleSwipe(),g(this._config.endCallback)}_move(t){this._deltaX=t.touches&&t.touches.length>1?0:t.touches[0].clientX-this._deltaX}_handleSwipe(){const t=Math.abs(this._deltaX);if(t<=40)return;const e=t/this._deltaX;this._deltaX=0,e&&g(e>0?this._config.rightCallback:this._config.leftCallback)}_initEvents(){this._supportPointerEvents?(N.on(this._element,tt,(t=>this._start(t))),N.on(this._element,et,(t=>this._end(t))),this._element.classList.add("pointer-event")):(N.on(this._element,G,(t=>this._start(t))),N.on(this._element,J,(t=>this._move(t))),N.on(this._element,Z,(t=>this._end(t))))}_eventIsPointerPenTouch(t){return this._supportPointerEvents&&("pen"===t.pointerType||"touch"===t.pointerType)}static isSupported(){return"ontouchstart"in document.documentElement||navigator.maxTouchPoints>0}}const ot=".bs.carousel",rt=".data-api",at="next",lt="prev",ct="left",ht="right",dt=`slide${ot}`,ut=`slid${ot}`,ft=`keydown${ot}`,pt=`mouseenter${ot}`,mt=`mouseleave${ot}`,gt=`dragstart${ot}`,_t=`load${ot}${rt}`,bt=`click${ot}${rt}`,vt="carousel",yt="active",wt=".active",At=".carousel-item",Et=wt+At,Tt={ArrowLeft:ht,ArrowRight:ct},Ct={interval:5e3,keyboard:!0,pause:"hover",ride:!1,touch:!0,wrap:!0},Ot={interval:"(number|boolean)",keyboard:"boolean",pause:"(string|boolean)",ride:"(boolean|string)",touch:"boolean",wrap:"boolean"};class xt extends W{constructor(t,e){super(t,e),this._interval=null,this._activeElement=null,this._isSliding=!1,this.touchTimeout=null,this._swipeHelper=null,this._indicatorsElement=z.findOne(".carousel-indicators",this._element),this._addEventListeners(),this._config.ride===vt&&this.cycle()}static get Default(){return Ct}static get DefaultType(){return Ot}static get NAME(){return"carousel"}next(){this._slide(at)}nextWhenVisible(){!document.hidden&&a(this._element)&&this.next()}prev(){this._slide(lt)}pause(){this._isSliding&&s(this._element),this._clearInterval()}cycle(){this._clearInterval(),this._updateInterval(),this._interval=setInterval((()=>this.nextWhenVisible()),this._config.interval)}_maybeEnableCycle(){this._config.ride&&(this._isSliding?N.one(this._element,ut,(()=>this.cycle())):this.cycle())}to(t){const e=this._getItems();if(t>e.length-1||t<0)return;if(this._isSliding)return void N.one(this._element,ut,(()=>this.to(t)));const i=this._getItemIndex(this._getActive());if(i===t)return;const n=t>i?at:lt;this._slide(n,e[t])}dispose(){this._swipeHelper&&this._swipeHelper.dispose(),super.dispose()}_configAfterMerge(t){return t.defaultInterval=t.interval,t}_addEventListeners(){this._config.keyboard&&N.on(this._element,ft,(t=>this._keydown(t))),"hover"===this._config.pause&&(N.on(this._element,pt,(()=>this.pause())),N.on(this._element,mt,(()=>this._maybeEnableCycle()))),this._config.touch&&st.isSupported()&&this._addTouchEventListeners()}_addTouchEventListeners(){for(const t of z.find(".carousel-item img",this._element))N.on(t,gt,(t=>t.preventDefault()));const t={leftCallback:()=>this._slide(this._directionToOrder(ct)),rightCallback:()=>this._slide(this._directionToOrder(ht)),endCallback:()=>{"hover"===this._config.pause&&(this.pause(),this.touchTimeout&&clearTimeout(this.touchTimeout),this.touchTimeout=setTimeout((()=>this._maybeEnableCycle()),500+this._config.interval))}};this._swipeHelper=new st(this._element,t)}_keydown(t){if(/input|textarea/i.test(t.target.tagName))return;const e=Tt[t.key];e&&(t.preventDefault(),this._slide(this._directionToOrder(e)))}_getItemIndex(t){return this._getItems().indexOf(t)}_setActiveIndicatorElement(t){if(!this._indicatorsElement)return;const e=z.findOne(wt,this._indicatorsElement);e.classList.remove(yt),e.removeAttribute("aria-current");const i=z.findOne(`[data-bs-slide-to="${t}"]`,this._indicatorsElement);i&&(i.classList.add(yt),i.setAttribute("aria-current","true"))}_updateInterval(){const t=this._activeElement||this._getActive();if(!t)return;const e=Number.parseInt(t.getAttribute("data-bs-interval"),10);this._config.interval=e||this._config.defaultInterval}_slide(t,e=null){if(this._isSliding)return;const i=this._getActive(),n=t===at,s=e||b(this._getItems(),i,n,this._config.wrap);if(s===i)return;const o=this._getItemIndex(s),r=e=>N.trigger(this._element,e,{relatedTarget:s,direction:this._orderToDirection(t),from:this._getItemIndex(i),to:o});if(r(dt).defaultPrevented)return;if(!i||!s)return;const a=Boolean(this._interval);this.pause(),this._isSliding=!0,this._setActiveIndicatorElement(o),this._activeElement=s;const l=n?"carousel-item-start":"carousel-item-end",c=n?"carousel-item-next":"carousel-item-prev";s.classList.add(c),d(s),i.classList.add(l),s.classList.add(l),this._queueCallback((()=>{s.classList.remove(l,c),s.classList.add(yt),i.classList.remove(yt,c,l),this._isSliding=!1,r(ut)}),i,this._isAnimated()),a&&this.cycle()}_isAnimated(){return this._element.classList.contains("slide")}_getActive(){return z.findOne(Et,this._element)}_getItems(){return z.find(At,this._element)}_clearInterval(){this._interval&&(clearInterval(this._interval),this._interval=null)}_directionToOrder(t){return p()?t===ct?lt:at:t===ct?at:lt}_orderToDirection(t){return p()?t===lt?ct:ht:t===lt?ht:ct}static jQueryInterface(t){return this.each((function(){const e=xt.getOrCreateInstance(this,t);if("number"!=typeof t){if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t]()}}else e.to(t)}))}}N.on(document,bt,"[data-bs-slide], [data-bs-slide-to]",(function(t){const e=z.getElementFromSelector(this);if(!e||!e.classList.contains(vt))return;t.preventDefault();const i=xt.getOrCreateInstance(e),n=this.getAttribute("data-bs-slide-to");return n?(i.to(n),void i._maybeEnableCycle()):"next"===F.getDataAttribute(this,"slide")?(i.next(),void i._maybeEnableCycle()):(i.prev(),void i._maybeEnableCycle())})),N.on(window,_t,(()=>{const t=z.find('[data-bs-ride="carousel"]');for(const e of t)xt.getOrCreateInstance(e)})),m(xt);const kt=".bs.collapse",Lt=`show${kt}`,St=`shown${kt}`,Dt=`hide${kt}`,$t=`hidden${kt}`,It=`click${kt}.data-api`,Nt="show",Pt="collapse",Mt="collapsing",jt=`:scope .${Pt} .${Pt}`,Ft='[data-bs-toggle="collapse"]',Ht={parent:null,toggle:!0},Wt={parent:"(null|element)",toggle:"boolean"};class Bt extends W{constructor(t,e){super(t,e),this._isTransitioning=!1,this._triggerArray=[];const i=z.find(Ft);for(const t of i){const e=z.getSelectorFromElement(t),i=z.find(e).filter((t=>t===this._element));null!==e&&i.length&&this._triggerArray.push(t)}this._initializeChildren(),this._config.parent||this._addAriaAndCollapsedClass(this._triggerArray,this._isShown()),this._config.toggle&&this.toggle()}static get Default(){return Ht}static get DefaultType(){return Wt}static get NAME(){return"collapse"}toggle(){this._isShown()?this.hide():this.show()}show(){if(this._isTransitioning||this._isShown())return;let t=[];if(this._config.parent&&(t=this._getFirstLevelChildren(".collapse.show, .collapse.collapsing").filter((t=>t!==this._element)).map((t=>Bt.getOrCreateInstance(t,{toggle:!1})))),t.length&&t[0]._isTransitioning)return;if(N.trigger(this._element,Lt).defaultPrevented)return;for(const e of t)e.hide();const e=this._getDimension();this._element.classList.remove(Pt),this._element.classList.add(Mt),this._element.style[e]=0,this._addAriaAndCollapsedClass(this._triggerArray,!0),this._isTransitioning=!0;const i=`scroll${e[0].toUpperCase()+e.slice(1)}`;this._queueCallback((()=>{this._isTransitioning=!1,this._element.classList.remove(Mt),this._element.classList.add(Pt,Nt),this._element.style[e]="",N.trigger(this._element,St)}),this._element,!0),this._element.style[e]=`${this._element[i]}px`}hide(){if(this._isTransitioning||!this._isShown())return;if(N.trigger(this._element,Dt).defaultPrevented)return;const t=this._getDimension();this._element.style[t]=`${this._element.getBoundingClientRect()[t]}px`,d(this._element),this._element.classList.add(Mt),this._element.classList.remove(Pt,Nt);for(const t of this._triggerArray){const e=z.getElementFromSelector(t);e&&!this._isShown(e)&&this._addAriaAndCollapsedClass([t],!1)}this._isTransitioning=!0,this._element.style[t]="",this._queueCallback((()=>{this._isTransitioning=!1,this._element.classList.remove(Mt),this._element.classList.add(Pt),N.trigger(this._element,$t)}),this._element,!0)}_isShown(t=this._element){return t.classList.contains(Nt)}_configAfterMerge(t){return t.toggle=Boolean(t.toggle),t.parent=r(t.parent),t}_getDimension(){return this._element.classList.contains("collapse-horizontal")?"width":"height"}_initializeChildren(){if(!this._config.parent)return;const t=this._getFirstLevelChildren(Ft);for(const e of t){const t=z.getElementFromSelector(e);t&&this._addAriaAndCollapsedClass([e],this._isShown(t))}}_getFirstLevelChildren(t){const e=z.find(jt,this._config.parent);return z.find(t,this._config.parent).filter((t=>!e.includes(t)))}_addAriaAndCollapsedClass(t,e){if(t.length)for(const i of t)i.classList.toggle("collapsed",!e),i.setAttribute("aria-expanded",e)}static jQueryInterface(t){const e={};return"string"==typeof t&&/show|hide/.test(t)&&(e.toggle=!1),this.each((function(){const i=Bt.getOrCreateInstance(this,e);if("string"==typeof t){if(void 0===i[t])throw new TypeError(`No method named "${t}"`);i[t]()}}))}}N.on(document,It,Ft,(function(t){("A"===t.target.tagName||t.delegateTarget&&"A"===t.delegateTarget.tagName)&&t.preventDefault();for(const t of z.getMultipleElementsFromSelector(this))Bt.getOrCreateInstance(t,{toggle:!1}).toggle()})),m(Bt);var zt="top",Rt="bottom",qt="right",Vt="left",Kt="auto",Qt=[zt,Rt,qt,Vt],Xt="start",Yt="end",Ut="clippingParents",Gt="viewport",Jt="popper",Zt="reference",te=Qt.reduce((function(t,e){return t.concat([e+"-"+Xt,e+"-"+Yt])}),[]),ee=[].concat(Qt,[Kt]).reduce((function(t,e){return t.concat([e,e+"-"+Xt,e+"-"+Yt])}),[]),ie="beforeRead",ne="read",se="afterRead",oe="beforeMain",re="main",ae="afterMain",le="beforeWrite",ce="write",he="afterWrite",de=[ie,ne,se,oe,re,ae,le,ce,he];function ue(t){return t?(t.nodeName||"").toLowerCase():null}function fe(t){if(null==t)return window;if("[object Window]"!==t.toString()){var e=t.ownerDocument;return e&&e.defaultView||window}return t}function pe(t){return t instanceof fe(t).Element||t instanceof Element}function me(t){return t instanceof fe(t).HTMLElement||t instanceof HTMLElement}function ge(t){return"undefined"!=typeof ShadowRoot&&(t instanceof fe(t).ShadowRoot||t instanceof ShadowRoot)}const _e={name:"applyStyles",enabled:!0,phase:"write",fn:function(t){var e=t.state;Object.keys(e.elements).forEach((function(t){var i=e.styles[t]||{},n=e.attributes[t]||{},s=e.elements[t];me(s)&&ue(s)&&(Object.assign(s.style,i),Object.keys(n).forEach((function(t){var e=n[t];!1===e?s.removeAttribute(t):s.setAttribute(t,!0===e?"":e)})))}))},effect:function(t){var e=t.state,i={popper:{position:e.options.strategy,left:"0",top:"0",margin:"0"},arrow:{position:"absolute"},reference:{}};return Object.assign(e.elements.popper.style,i.popper),e.styles=i,e.elements.arrow&&Object.assign(e.elements.arrow.style,i.arrow),function(){Object.keys(e.elements).forEach((function(t){var n=e.elements[t],s=e.attributes[t]||{},o=Object.keys(e.styles.hasOwnProperty(t)?e.styles[t]:i[t]).reduce((function(t,e){return t[e]="",t}),{});me(n)&&ue(n)&&(Object.assign(n.style,o),Object.keys(s).forEach((function(t){n.removeAttribute(t)})))}))}},requires:["computeStyles"]};function be(t){return t.split("-")[0]}var ve=Math.max,ye=Math.min,we=Math.round;function Ae(){var t=navigator.userAgentData;return null!=t&&t.brands&&Array.isArray(t.brands)?t.brands.map((function(t){return t.brand+"/"+t.version})).join(" "):navigator.userAgent}function Ee(){return!/^((?!chrome|android).)*safari/i.test(Ae())}function Te(t,e,i){void 0===e&&(e=!1),void 0===i&&(i=!1);var n=t.getBoundingClientRect(),s=1,o=1;e&&me(t)&&(s=t.offsetWidth>0&&we(n.width)/t.offsetWidth||1,o=t.offsetHeight>0&&we(n.height)/t.offsetHeight||1);var r=(pe(t)?fe(t):window).visualViewport,a=!Ee()&&i,l=(n.left+(a&&r?r.offsetLeft:0))/s,c=(n.top+(a&&r?r.offsetTop:0))/o,h=n.width/s,d=n.height/o;return{width:h,height:d,top:c,right:l+h,bottom:c+d,left:l,x:l,y:c}}function Ce(t){var e=Te(t),i=t.offsetWidth,n=t.offsetHeight;return Math.abs(e.width-i)<=1&&(i=e.width),Math.abs(e.height-n)<=1&&(n=e.height),{x:t.offsetLeft,y:t.offsetTop,width:i,height:n}}function Oe(t,e){var i=e.getRootNode&&e.getRootNode();if(t.contains(e))return!0;if(i&&ge(i)){var n=e;do{if(n&&t.isSameNode(n))return!0;n=n.parentNode||n.host}while(n)}return!1}function xe(t){return fe(t).getComputedStyle(t)}function ke(t){return["table","td","th"].indexOf(ue(t))>=0}function Le(t){return((pe(t)?t.ownerDocument:t.document)||window.document).documentElement}function Se(t){return"html"===ue(t)?t:t.assignedSlot||t.parentNode||(ge(t)?t.host:null)||Le(t)}function De(t){return me(t)&&"fixed"!==xe(t).position?t.offsetParent:null}function $e(t){for(var e=fe(t),i=De(t);i&&ke(i)&&"static"===xe(i).position;)i=De(i);return i&&("html"===ue(i)||"body"===ue(i)&&"static"===xe(i).position)?e:i||function(t){var e=/firefox/i.test(Ae());if(/Trident/i.test(Ae())&&me(t)&&"fixed"===xe(t).position)return null;var i=Se(t);for(ge(i)&&(i=i.host);me(i)&&["html","body"].indexOf(ue(i))<0;){var n=xe(i);if("none"!==n.transform||"none"!==n.perspective||"paint"===n.contain||-1!==["transform","perspective"].indexOf(n.willChange)||e&&"filter"===n.willChange||e&&n.filter&&"none"!==n.filter)return i;i=i.parentNode}return null}(t)||e}function Ie(t){return["top","bottom"].indexOf(t)>=0?"x":"y"}function Ne(t,e,i){return ve(t,ye(e,i))}function Pe(t){return Object.assign({},{top:0,right:0,bottom:0,left:0},t)}function Me(t,e){return e.reduce((function(e,i){return e[i]=t,e}),{})}const je={name:"arrow",enabled:!0,phase:"main",fn:function(t){var e,i=t.state,n=t.name,s=t.options,o=i.elements.arrow,r=i.modifiersData.popperOffsets,a=be(i.placement),l=Ie(a),c=[Vt,qt].indexOf(a)>=0?"height":"width";if(o&&r){var h=function(t,e){return Pe("number"!=typeof(t="function"==typeof t?t(Object.assign({},e.rects,{placement:e.placement})):t)?t:Me(t,Qt))}(s.padding,i),d=Ce(o),u="y"===l?zt:Vt,f="y"===l?Rt:qt,p=i.rects.reference[c]+i.rects.reference[l]-r[l]-i.rects.popper[c],m=r[l]-i.rects.reference[l],g=$e(o),_=g?"y"===l?g.clientHeight||0:g.clientWidth||0:0,b=p/2-m/2,v=h[u],y=_-d[c]-h[f],w=_/2-d[c]/2+b,A=Ne(v,w,y),E=l;i.modifiersData[n]=((e={})[E]=A,e.centerOffset=A-w,e)}},effect:function(t){var e=t.state,i=t.options.element,n=void 0===i?"[data-popper-arrow]":i;null!=n&&("string"!=typeof n||(n=e.elements.popper.querySelector(n)))&&Oe(e.elements.popper,n)&&(e.elements.arrow=n)},requires:["popperOffsets"],requiresIfExists:["preventOverflow"]};function Fe(t){return t.split("-")[1]}var He={top:"auto",right:"auto",bottom:"auto",left:"auto"};function We(t){var e,i=t.popper,n=t.popperRect,s=t.placement,o=t.variation,r=t.offsets,a=t.position,l=t.gpuAcceleration,c=t.adaptive,h=t.roundOffsets,d=t.isFixed,u=r.x,f=void 0===u?0:u,p=r.y,m=void 0===p?0:p,g="function"==typeof h?h({x:f,y:m}):{x:f,y:m};f=g.x,m=g.y;var _=r.hasOwnProperty("x"),b=r.hasOwnProperty("y"),v=Vt,y=zt,w=window;if(c){var A=$e(i),E="clientHeight",T="clientWidth";A===fe(i)&&"static"!==xe(A=Le(i)).position&&"absolute"===a&&(E="scrollHeight",T="scrollWidth"),(s===zt||(s===Vt||s===qt)&&o===Yt)&&(y=Rt,m-=(d&&A===w&&w.visualViewport?w.visualViewport.height:A[E])-n.height,m*=l?1:-1),s!==Vt&&(s!==zt&&s!==Rt||o!==Yt)||(v=qt,f-=(d&&A===w&&w.visualViewport?w.visualViewport.width:A[T])-n.width,f*=l?1:-1)}var C,O=Object.assign({position:a},c&&He),x=!0===h?function(t,e){var i=t.x,n=t.y,s=e.devicePixelRatio||1;return{x:we(i*s)/s||0,y:we(n*s)/s||0}}({x:f,y:m},fe(i)):{x:f,y:m};return f=x.x,m=x.y,l?Object.assign({},O,((C={})[y]=b?"0":"",C[v]=_?"0":"",C.transform=(w.devicePixelRatio||1)<=1?"translate("+f+"px, "+m+"px)":"translate3d("+f+"px, "+m+"px, 0)",C)):Object.assign({},O,((e={})[y]=b?m+"px":"",e[v]=_?f+"px":"",e.transform="",e))}const Be={name:"computeStyles",enabled:!0,phase:"beforeWrite",fn:function(t){var e=t.state,i=t.options,n=i.gpuAcceleration,s=void 0===n||n,o=i.adaptive,r=void 0===o||o,a=i.roundOffsets,l=void 0===a||a,c={placement:be(e.placement),variation:Fe(e.placement),popper:e.elements.popper,popperRect:e.rects.popper,gpuAcceleration:s,isFixed:"fixed"===e.options.strategy};null!=e.modifiersData.popperOffsets&&(e.styles.popper=Object.assign({},e.styles.popper,We(Object.assign({},c,{offsets:e.modifiersData.popperOffsets,position:e.options.strategy,adaptive:r,roundOffsets:l})))),null!=e.modifiersData.arrow&&(e.styles.arrow=Object.assign({},e.styles.arrow,We(Object.assign({},c,{offsets:e.modifiersData.arrow,position:"absolute",adaptive:!1,roundOffsets:l})))),e.attributes.popper=Object.assign({},e.attributes.popper,{"data-popper-placement":e.placement})},data:{}};var ze={passive:!0};const Re={name:"eventListeners",enabled:!0,phase:"write",fn:function(){},effect:function(t){var e=t.state,i=t.instance,n=t.options,s=n.scroll,o=void 0===s||s,r=n.resize,a=void 0===r||r,l=fe(e.elements.popper),c=[].concat(e.scrollParents.reference,e.scrollParents.popper);return o&&c.forEach((function(t){t.addEventListener("scroll",i.update,ze)})),a&&l.addEventListener("resize",i.update,ze),function(){o&&c.forEach((function(t){t.removeEventListener("scroll",i.update,ze)})),a&&l.removeEventListener("resize",i.update,ze)}},data:{}};var qe={left:"right",right:"left",bottom:"top",top:"bottom"};function Ve(t){return t.replace(/left|right|bottom|top/g,(function(t){return qe[t]}))}var Ke={start:"end",end:"start"};function Qe(t){return t.replace(/start|end/g,(function(t){return Ke[t]}))}function Xe(t){var e=fe(t);return{scrollLeft:e.pageXOffset,scrollTop:e.pageYOffset}}function Ye(t){return Te(Le(t)).left+Xe(t).scrollLeft}function Ue(t){var e=xe(t),i=e.overflow,n=e.overflowX,s=e.overflowY;return/auto|scroll|overlay|hidden/.test(i+s+n)}function Ge(t){return["html","body","#document"].indexOf(ue(t))>=0?t.ownerDocument.body:me(t)&&Ue(t)?t:Ge(Se(t))}function Je(t,e){var i;void 0===e&&(e=[]);var n=Ge(t),s=n===(null==(i=t.ownerDocument)?void 0:i.body),o=fe(n),r=s?[o].concat(o.visualViewport||[],Ue(n)?n:[]):n,a=e.concat(r);return s?a:a.concat(Je(Se(r)))}function Ze(t){return Object.assign({},t,{left:t.x,top:t.y,right:t.x+t.width,bottom:t.y+t.height})}function ti(t,e,i){return e===Gt?Ze(function(t,e){var i=fe(t),n=Le(t),s=i.visualViewport,o=n.clientWidth,r=n.clientHeight,a=0,l=0;if(s){o=s.width,r=s.height;var c=Ee();(c||!c&&"fixed"===e)&&(a=s.offsetLeft,l=s.offsetTop)}return{width:o,height:r,x:a+Ye(t),y:l}}(t,i)):pe(e)?function(t,e){var i=Te(t,!1,"fixed"===e);return i.top=i.top+t.clientTop,i.left=i.left+t.clientLeft,i.bottom=i.top+t.clientHeight,i.right=i.left+t.clientWidth,i.width=t.clientWidth,i.height=t.clientHeight,i.x=i.left,i.y=i.top,i}(e,i):Ze(function(t){var e,i=Le(t),n=Xe(t),s=null==(e=t.ownerDocument)?void 0:e.body,o=ve(i.scrollWidth,i.clientWidth,s?s.scrollWidth:0,s?s.clientWidth:0),r=ve(i.scrollHeight,i.clientHeight,s?s.scrollHeight:0,s?s.clientHeight:0),a=-n.scrollLeft+Ye(t),l=-n.scrollTop;return"rtl"===xe(s||i).direction&&(a+=ve(i.clientWidth,s?s.clientWidth:0)-o),{width:o,height:r,x:a,y:l}}(Le(t)))}function ei(t){var e,i=t.reference,n=t.element,s=t.placement,o=s?be(s):null,r=s?Fe(s):null,a=i.x+i.width/2-n.width/2,l=i.y+i.height/2-n.height/2;switch(o){case zt:e={x:a,y:i.y-n.height};break;case Rt:e={x:a,y:i.y+i.height};break;case qt:e={x:i.x+i.width,y:l};break;case Vt:e={x:i.x-n.width,y:l};break;default:e={x:i.x,y:i.y}}var c=o?Ie(o):null;if(null!=c){var h="y"===c?"height":"width";switch(r){case Xt:e[c]=e[c]-(i[h]/2-n[h]/2);break;case Yt:e[c]=e[c]+(i[h]/2-n[h]/2)}}return e}function ii(t,e){void 0===e&&(e={});var i=e,n=i.placement,s=void 0===n?t.placement:n,o=i.strategy,r=void 0===o?t.strategy:o,a=i.boundary,l=void 0===a?Ut:a,c=i.rootBoundary,h=void 0===c?Gt:c,d=i.elementContext,u=void 0===d?Jt:d,f=i.altBoundary,p=void 0!==f&&f,m=i.padding,g=void 0===m?0:m,_=Pe("number"!=typeof g?g:Me(g,Qt)),b=u===Jt?Zt:Jt,v=t.rects.popper,y=t.elements[p?b:u],w=function(t,e,i,n){var s="clippingParents"===e?function(t){var e=Je(Se(t)),i=["absolute","fixed"].indexOf(xe(t).position)>=0&&me(t)?$e(t):t;return pe(i)?e.filter((function(t){return pe(t)&&Oe(t,i)&&"body"!==ue(t)})):[]}(t):[].concat(e),o=[].concat(s,[i]),r=o[0],a=o.reduce((function(e,i){var s=ti(t,i,n);return e.top=ve(s.top,e.top),e.right=ye(s.right,e.right),e.bottom=ye(s.bottom,e.bottom),e.left=ve(s.left,e.left),e}),ti(t,r,n));return a.width=a.right-a.left,a.height=a.bottom-a.top,a.x=a.left,a.y=a.top,a}(pe(y)?y:y.contextElement||Le(t.elements.popper),l,h,r),A=Te(t.elements.reference),E=ei({reference:A,element:v,strategy:"absolute",placement:s}),T=Ze(Object.assign({},v,E)),C=u===Jt?T:A,O={top:w.top-C.top+_.top,bottom:C.bottom-w.bottom+_.bottom,left:w.left-C.left+_.left,right:C.right-w.right+_.right},x=t.modifiersData.offset;if(u===Jt&&x){var k=x[s];Object.keys(O).forEach((function(t){var e=[qt,Rt].indexOf(t)>=0?1:-1,i=[zt,Rt].indexOf(t)>=0?"y":"x";O[t]+=k[i]*e}))}return O}function ni(t,e){void 0===e&&(e={});var i=e,n=i.placement,s=i.boundary,o=i.rootBoundary,r=i.padding,a=i.flipVariations,l=i.allowedAutoPlacements,c=void 0===l?ee:l,h=Fe(n),d=h?a?te:te.filter((function(t){return Fe(t)===h})):Qt,u=d.filter((function(t){return c.indexOf(t)>=0}));0===u.length&&(u=d);var f=u.reduce((function(e,i){return e[i]=ii(t,{placement:i,boundary:s,rootBoundary:o,padding:r})[be(i)],e}),{});return Object.keys(f).sort((function(t,e){return f[t]-f[e]}))}const si={name:"flip",enabled:!0,phase:"main",fn:function(t){var e=t.state,i=t.options,n=t.name;if(!e.modifiersData[n]._skip){for(var s=i.mainAxis,o=void 0===s||s,r=i.altAxis,a=void 0===r||r,l=i.fallbackPlacements,c=i.padding,h=i.boundary,d=i.rootBoundary,u=i.altBoundary,f=i.flipVariations,p=void 0===f||f,m=i.allowedAutoPlacements,g=e.options.placement,_=be(g),b=l||(_!==g&&p?function(t){if(be(t)===Kt)return[];var e=Ve(t);return[Qe(t),e,Qe(e)]}(g):[Ve(g)]),v=[g].concat(b).reduce((function(t,i){return t.concat(be(i)===Kt?ni(e,{placement:i,boundary:h,rootBoundary:d,padding:c,flipVariations:p,allowedAutoPlacements:m}):i)}),[]),y=e.rects.reference,w=e.rects.popper,A=new Map,E=!0,T=v[0],C=0;C=0,S=L?"width":"height",D=ii(e,{placement:O,boundary:h,rootBoundary:d,altBoundary:u,padding:c}),$=L?k?qt:Vt:k?Rt:zt;y[S]>w[S]&&($=Ve($));var I=Ve($),N=[];if(o&&N.push(D[x]<=0),a&&N.push(D[$]<=0,D[I]<=0),N.every((function(t){return t}))){T=O,E=!1;break}A.set(O,N)}if(E)for(var P=function(t){var e=v.find((function(e){var i=A.get(e);if(i)return i.slice(0,t).every((function(t){return t}))}));if(e)return T=e,"break"},M=p?3:1;M>0&&"break"!==P(M);M--);e.placement!==T&&(e.modifiersData[n]._skip=!0,e.placement=T,e.reset=!0)}},requiresIfExists:["offset"],data:{_skip:!1}};function oi(t,e,i){return void 0===i&&(i={x:0,y:0}),{top:t.top-e.height-i.y,right:t.right-e.width+i.x,bottom:t.bottom-e.height+i.y,left:t.left-e.width-i.x}}function ri(t){return[zt,qt,Rt,Vt].some((function(e){return t[e]>=0}))}const ai={name:"hide",enabled:!0,phase:"main",requiresIfExists:["preventOverflow"],fn:function(t){var e=t.state,i=t.name,n=e.rects.reference,s=e.rects.popper,o=e.modifiersData.preventOverflow,r=ii(e,{elementContext:"reference"}),a=ii(e,{altBoundary:!0}),l=oi(r,n),c=oi(a,s,o),h=ri(l),d=ri(c);e.modifiersData[i]={referenceClippingOffsets:l,popperEscapeOffsets:c,isReferenceHidden:h,hasPopperEscaped:d},e.attributes.popper=Object.assign({},e.attributes.popper,{"data-popper-reference-hidden":h,"data-popper-escaped":d})}},li={name:"offset",enabled:!0,phase:"main",requires:["popperOffsets"],fn:function(t){var e=t.state,i=t.options,n=t.name,s=i.offset,o=void 0===s?[0,0]:s,r=ee.reduce((function(t,i){return t[i]=function(t,e,i){var n=be(t),s=[Vt,zt].indexOf(n)>=0?-1:1,o="function"==typeof i?i(Object.assign({},e,{placement:t})):i,r=o[0],a=o[1];return r=r||0,a=(a||0)*s,[Vt,qt].indexOf(n)>=0?{x:a,y:r}:{x:r,y:a}}(i,e.rects,o),t}),{}),a=r[e.placement],l=a.x,c=a.y;null!=e.modifiersData.popperOffsets&&(e.modifiersData.popperOffsets.x+=l,e.modifiersData.popperOffsets.y+=c),e.modifiersData[n]=r}},ci={name:"popperOffsets",enabled:!0,phase:"read",fn:function(t){var e=t.state,i=t.name;e.modifiersData[i]=ei({reference:e.rects.reference,element:e.rects.popper,strategy:"absolute",placement:e.placement})},data:{}},hi={name:"preventOverflow",enabled:!0,phase:"main",fn:function(t){var e=t.state,i=t.options,n=t.name,s=i.mainAxis,o=void 0===s||s,r=i.altAxis,a=void 0!==r&&r,l=i.boundary,c=i.rootBoundary,h=i.altBoundary,d=i.padding,u=i.tether,f=void 0===u||u,p=i.tetherOffset,m=void 0===p?0:p,g=ii(e,{boundary:l,rootBoundary:c,padding:d,altBoundary:h}),_=be(e.placement),b=Fe(e.placement),v=!b,y=Ie(_),w="x"===y?"y":"x",A=e.modifiersData.popperOffsets,E=e.rects.reference,T=e.rects.popper,C="function"==typeof m?m(Object.assign({},e.rects,{placement:e.placement})):m,O="number"==typeof C?{mainAxis:C,altAxis:C}:Object.assign({mainAxis:0,altAxis:0},C),x=e.modifiersData.offset?e.modifiersData.offset[e.placement]:null,k={x:0,y:0};if(A){if(o){var L,S="y"===y?zt:Vt,D="y"===y?Rt:qt,$="y"===y?"height":"width",I=A[y],N=I+g[S],P=I-g[D],M=f?-T[$]/2:0,j=b===Xt?E[$]:T[$],F=b===Xt?-T[$]:-E[$],H=e.elements.arrow,W=f&&H?Ce(H):{width:0,height:0},B=e.modifiersData["arrow#persistent"]?e.modifiersData["arrow#persistent"].padding:{top:0,right:0,bottom:0,left:0},z=B[S],R=B[D],q=Ne(0,E[$],W[$]),V=v?E[$]/2-M-q-z-O.mainAxis:j-q-z-O.mainAxis,K=v?-E[$]/2+M+q+R+O.mainAxis:F+q+R+O.mainAxis,Q=e.elements.arrow&&$e(e.elements.arrow),X=Q?"y"===y?Q.clientTop||0:Q.clientLeft||0:0,Y=null!=(L=null==x?void 0:x[y])?L:0,U=I+K-Y,G=Ne(f?ye(N,I+V-Y-X):N,I,f?ve(P,U):P);A[y]=G,k[y]=G-I}if(a){var J,Z="x"===y?zt:Vt,tt="x"===y?Rt:qt,et=A[w],it="y"===w?"height":"width",nt=et+g[Z],st=et-g[tt],ot=-1!==[zt,Vt].indexOf(_),rt=null!=(J=null==x?void 0:x[w])?J:0,at=ot?nt:et-E[it]-T[it]-rt+O.altAxis,lt=ot?et+E[it]+T[it]-rt-O.altAxis:st,ct=f&&ot?function(t,e,i){var n=Ne(t,e,i);return n>i?i:n}(at,et,lt):Ne(f?at:nt,et,f?lt:st);A[w]=ct,k[w]=ct-et}e.modifiersData[n]=k}},requiresIfExists:["offset"]};function di(t,e,i){void 0===i&&(i=!1);var n,s,o=me(e),r=me(e)&&function(t){var e=t.getBoundingClientRect(),i=we(e.width)/t.offsetWidth||1,n=we(e.height)/t.offsetHeight||1;return 1!==i||1!==n}(e),a=Le(e),l=Te(t,r,i),c={scrollLeft:0,scrollTop:0},h={x:0,y:0};return(o||!o&&!i)&&(("body"!==ue(e)||Ue(a))&&(c=(n=e)!==fe(n)&&me(n)?{scrollLeft:(s=n).scrollLeft,scrollTop:s.scrollTop}:Xe(n)),me(e)?((h=Te(e,!0)).x+=e.clientLeft,h.y+=e.clientTop):a&&(h.x=Ye(a))),{x:l.left+c.scrollLeft-h.x,y:l.top+c.scrollTop-h.y,width:l.width,height:l.height}}function ui(t){var e=new Map,i=new Set,n=[];function s(t){i.add(t.name),[].concat(t.requires||[],t.requiresIfExists||[]).forEach((function(t){if(!i.has(t)){var n=e.get(t);n&&s(n)}})),n.push(t)}return t.forEach((function(t){e.set(t.name,t)})),t.forEach((function(t){i.has(t.name)||s(t)})),n}var fi={placement:"bottom",modifiers:[],strategy:"absolute"};function pi(){for(var t=arguments.length,e=new Array(t),i=0;iNumber.parseInt(t,10))):"function"==typeof t?e=>t(e,this._element):t}_getPopperConfig(){const t={placement:this._getPlacement(),modifiers:[{name:"preventOverflow",options:{boundary:this._config.boundary}},{name:"offset",options:{offset:this._getOffset()}}]};return(this._inNavbar||"static"===this._config.display)&&(F.setDataAttribute(this._menu,"popper","static"),t.modifiers=[{name:"applyStyles",enabled:!1}]),{...t,...g(this._config.popperConfig,[t])}}_selectMenuItem({key:t,target:e}){const i=z.find(".dropdown-menu .dropdown-item:not(.disabled):not(:disabled)",this._menu).filter((t=>a(t)));i.length&&b(i,e,t===Ti,!i.includes(e)).focus()}static jQueryInterface(t){return this.each((function(){const e=qi.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}}))}static clearMenus(t){if(2===t.button||"keyup"===t.type&&"Tab"!==t.key)return;const e=z.find(Ni);for(const i of e){const e=qi.getInstance(i);if(!e||!1===e._config.autoClose)continue;const n=t.composedPath(),s=n.includes(e._menu);if(n.includes(e._element)||"inside"===e._config.autoClose&&!s||"outside"===e._config.autoClose&&s)continue;if(e._menu.contains(t.target)&&("keyup"===t.type&&"Tab"===t.key||/input|select|option|textarea|form/i.test(t.target.tagName)))continue;const o={relatedTarget:e._element};"click"===t.type&&(o.clickEvent=t),e._completeHide(o)}}static dataApiKeydownHandler(t){const e=/input|textarea/i.test(t.target.tagName),i="Escape"===t.key,n=[Ei,Ti].includes(t.key);if(!n&&!i)return;if(e&&!i)return;t.preventDefault();const s=this.matches(Ii)?this:z.prev(this,Ii)[0]||z.next(this,Ii)[0]||z.findOne(Ii,t.delegateTarget.parentNode),o=qi.getOrCreateInstance(s);if(n)return t.stopPropagation(),o.show(),void o._selectMenuItem(t);o._isShown()&&(t.stopPropagation(),o.hide(),s.focus())}}N.on(document,Si,Ii,qi.dataApiKeydownHandler),N.on(document,Si,Pi,qi.dataApiKeydownHandler),N.on(document,Li,qi.clearMenus),N.on(document,Di,qi.clearMenus),N.on(document,Li,Ii,(function(t){t.preventDefault(),qi.getOrCreateInstance(this).toggle()})),m(qi);const Vi="backdrop",Ki="show",Qi=`mousedown.bs.${Vi}`,Xi={className:"modal-backdrop",clickCallback:null,isAnimated:!1,isVisible:!0,rootElement:"body"},Yi={className:"string",clickCallback:"(function|null)",isAnimated:"boolean",isVisible:"boolean",rootElement:"(element|string)"};class Ui extends H{constructor(t){super(),this._config=this._getConfig(t),this._isAppended=!1,this._element=null}static get Default(){return Xi}static get DefaultType(){return Yi}static get NAME(){return Vi}show(t){if(!this._config.isVisible)return void g(t);this._append();const e=this._getElement();this._config.isAnimated&&d(e),e.classList.add(Ki),this._emulateAnimation((()=>{g(t)}))}hide(t){this._config.isVisible?(this._getElement().classList.remove(Ki),this._emulateAnimation((()=>{this.dispose(),g(t)}))):g(t)}dispose(){this._isAppended&&(N.off(this._element,Qi),this._element.remove(),this._isAppended=!1)}_getElement(){if(!this._element){const t=document.createElement("div");t.className=this._config.className,this._config.isAnimated&&t.classList.add("fade"),this._element=t}return this._element}_configAfterMerge(t){return t.rootElement=r(t.rootElement),t}_append(){if(this._isAppended)return;const t=this._getElement();this._config.rootElement.append(t),N.on(t,Qi,(()=>{g(this._config.clickCallback)})),this._isAppended=!0}_emulateAnimation(t){_(t,this._getElement(),this._config.isAnimated)}}const Gi=".bs.focustrap",Ji=`focusin${Gi}`,Zi=`keydown.tab${Gi}`,tn="backward",en={autofocus:!0,trapElement:null},nn={autofocus:"boolean",trapElement:"element"};class sn extends H{constructor(t){super(),this._config=this._getConfig(t),this._isActive=!1,this._lastTabNavDirection=null}static get Default(){return en}static get DefaultType(){return nn}static get NAME(){return"focustrap"}activate(){this._isActive||(this._config.autofocus&&this._config.trapElement.focus(),N.off(document,Gi),N.on(document,Ji,(t=>this._handleFocusin(t))),N.on(document,Zi,(t=>this._handleKeydown(t))),this._isActive=!0)}deactivate(){this._isActive&&(this._isActive=!1,N.off(document,Gi))}_handleFocusin(t){const{trapElement:e}=this._config;if(t.target===document||t.target===e||e.contains(t.target))return;const i=z.focusableChildren(e);0===i.length?e.focus():this._lastTabNavDirection===tn?i[i.length-1].focus():i[0].focus()}_handleKeydown(t){"Tab"===t.key&&(this._lastTabNavDirection=t.shiftKey?tn:"forward")}}const on=".fixed-top, .fixed-bottom, .is-fixed, .sticky-top",rn=".sticky-top",an="padding-right",ln="margin-right";class cn{constructor(){this._element=document.body}getWidth(){const t=document.documentElement.clientWidth;return Math.abs(window.innerWidth-t)}hide(){const t=this.getWidth();this._disableOverFlow(),this._setElementAttributes(this._element,an,(e=>e+t)),this._setElementAttributes(on,an,(e=>e+t)),this._setElementAttributes(rn,ln,(e=>e-t))}reset(){this._resetElementAttributes(this._element,"overflow"),this._resetElementAttributes(this._element,an),this._resetElementAttributes(on,an),this._resetElementAttributes(rn,ln)}isOverflowing(){return this.getWidth()>0}_disableOverFlow(){this._saveInitialAttribute(this._element,"overflow"),this._element.style.overflow="hidden"}_setElementAttributes(t,e,i){const n=this.getWidth();this._applyManipulationCallback(t,(t=>{if(t!==this._element&&window.innerWidth>t.clientWidth+n)return;this._saveInitialAttribute(t,e);const s=window.getComputedStyle(t).getPropertyValue(e);t.style.setProperty(e,`${i(Number.parseFloat(s))}px`)}))}_saveInitialAttribute(t,e){const i=t.style.getPropertyValue(e);i&&F.setDataAttribute(t,e,i)}_resetElementAttributes(t,e){this._applyManipulationCallback(t,(t=>{const i=F.getDataAttribute(t,e);null!==i?(F.removeDataAttribute(t,e),t.style.setProperty(e,i)):t.style.removeProperty(e)}))}_applyManipulationCallback(t,e){if(o(t))e(t);else for(const i of z.find(t,this._element))e(i)}}const hn=".bs.modal",dn=`hide${hn}`,un=`hidePrevented${hn}`,fn=`hidden${hn}`,pn=`show${hn}`,mn=`shown${hn}`,gn=`resize${hn}`,_n=`click.dismiss${hn}`,bn=`mousedown.dismiss${hn}`,vn=`keydown.dismiss${hn}`,yn=`click${hn}.data-api`,wn="modal-open",An="show",En="modal-static",Tn={backdrop:!0,focus:!0,keyboard:!0},Cn={backdrop:"(boolean|string)",focus:"boolean",keyboard:"boolean"};class On extends W{constructor(t,e){super(t,e),this._dialog=z.findOne(".modal-dialog",this._element),this._backdrop=this._initializeBackDrop(),this._focustrap=this._initializeFocusTrap(),this._isShown=!1,this._isTransitioning=!1,this._scrollBar=new cn,this._addEventListeners()}static get Default(){return Tn}static get DefaultType(){return Cn}static get NAME(){return"modal"}toggle(t){return this._isShown?this.hide():this.show(t)}show(t){this._isShown||this._isTransitioning||N.trigger(this._element,pn,{relatedTarget:t}).defaultPrevented||(this._isShown=!0,this._isTransitioning=!0,this._scrollBar.hide(),document.body.classList.add(wn),this._adjustDialog(),this._backdrop.show((()=>this._showElement(t))))}hide(){this._isShown&&!this._isTransitioning&&(N.trigger(this._element,dn).defaultPrevented||(this._isShown=!1,this._isTransitioning=!0,this._focustrap.deactivate(),this._element.classList.remove(An),this._queueCallback((()=>this._hideModal()),this._element,this._isAnimated())))}dispose(){N.off(window,hn),N.off(this._dialog,hn),this._backdrop.dispose(),this._focustrap.deactivate(),super.dispose()}handleUpdate(){this._adjustDialog()}_initializeBackDrop(){return new Ui({isVisible:Boolean(this._config.backdrop),isAnimated:this._isAnimated()})}_initializeFocusTrap(){return new sn({trapElement:this._element})}_showElement(t){document.body.contains(this._element)||document.body.append(this._element),this._element.style.display="block",this._element.removeAttribute("aria-hidden"),this._element.setAttribute("aria-modal",!0),this._element.setAttribute("role","dialog"),this._element.scrollTop=0;const e=z.findOne(".modal-body",this._dialog);e&&(e.scrollTop=0),d(this._element),this._element.classList.add(An),this._queueCallback((()=>{this._config.focus&&this._focustrap.activate(),this._isTransitioning=!1,N.trigger(this._element,mn,{relatedTarget:t})}),this._dialog,this._isAnimated())}_addEventListeners(){N.on(this._element,vn,(t=>{"Escape"===t.key&&(this._config.keyboard?this.hide():this._triggerBackdropTransition())})),N.on(window,gn,(()=>{this._isShown&&!this._isTransitioning&&this._adjustDialog()})),N.on(this._element,bn,(t=>{N.one(this._element,_n,(e=>{this._element===t.target&&this._element===e.target&&("static"!==this._config.backdrop?this._config.backdrop&&this.hide():this._triggerBackdropTransition())}))}))}_hideModal(){this._element.style.display="none",this._element.setAttribute("aria-hidden",!0),this._element.removeAttribute("aria-modal"),this._element.removeAttribute("role"),this._isTransitioning=!1,this._backdrop.hide((()=>{document.body.classList.remove(wn),this._resetAdjustments(),this._scrollBar.reset(),N.trigger(this._element,fn)}))}_isAnimated(){return this._element.classList.contains("fade")}_triggerBackdropTransition(){if(N.trigger(this._element,un).defaultPrevented)return;const t=this._element.scrollHeight>document.documentElement.clientHeight,e=this._element.style.overflowY;"hidden"===e||this._element.classList.contains(En)||(t||(this._element.style.overflowY="hidden"),this._element.classList.add(En),this._queueCallback((()=>{this._element.classList.remove(En),this._queueCallback((()=>{this._element.style.overflowY=e}),this._dialog)}),this._dialog),this._element.focus())}_adjustDialog(){const t=this._element.scrollHeight>document.documentElement.clientHeight,e=this._scrollBar.getWidth(),i=e>0;if(i&&!t){const t=p()?"paddingLeft":"paddingRight";this._element.style[t]=`${e}px`}if(!i&&t){const t=p()?"paddingRight":"paddingLeft";this._element.style[t]=`${e}px`}}_resetAdjustments(){this._element.style.paddingLeft="",this._element.style.paddingRight=""}static jQueryInterface(t,e){return this.each((function(){const i=On.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===i[t])throw new TypeError(`No method named "${t}"`);i[t](e)}}))}}N.on(document,yn,'[data-bs-toggle="modal"]',(function(t){const e=z.getElementFromSelector(this);["A","AREA"].includes(this.tagName)&&t.preventDefault(),N.one(e,pn,(t=>{t.defaultPrevented||N.one(e,fn,(()=>{a(this)&&this.focus()}))}));const i=z.findOne(".modal.show");i&&On.getInstance(i).hide(),On.getOrCreateInstance(e).toggle(this)})),R(On),m(On);const xn=".bs.offcanvas",kn=".data-api",Ln=`load${xn}${kn}`,Sn="show",Dn="showing",$n="hiding",In=".offcanvas.show",Nn=`show${xn}`,Pn=`shown${xn}`,Mn=`hide${xn}`,jn=`hidePrevented${xn}`,Fn=`hidden${xn}`,Hn=`resize${xn}`,Wn=`click${xn}${kn}`,Bn=`keydown.dismiss${xn}`,zn={backdrop:!0,keyboard:!0,scroll:!1},Rn={backdrop:"(boolean|string)",keyboard:"boolean",scroll:"boolean"};class qn extends W{constructor(t,e){super(t,e),this._isShown=!1,this._backdrop=this._initializeBackDrop(),this._focustrap=this._initializeFocusTrap(),this._addEventListeners()}static get Default(){return zn}static get DefaultType(){return Rn}static get NAME(){return"offcanvas"}toggle(t){return this._isShown?this.hide():this.show(t)}show(t){this._isShown||N.trigger(this._element,Nn,{relatedTarget:t}).defaultPrevented||(this._isShown=!0,this._backdrop.show(),this._config.scroll||(new cn).hide(),this._element.setAttribute("aria-modal",!0),this._element.setAttribute("role","dialog"),this._element.classList.add(Dn),this._queueCallback((()=>{this._config.scroll&&!this._config.backdrop||this._focustrap.activate(),this._element.classList.add(Sn),this._element.classList.remove(Dn),N.trigger(this._element,Pn,{relatedTarget:t})}),this._element,!0))}hide(){this._isShown&&(N.trigger(this._element,Mn).defaultPrevented||(this._focustrap.deactivate(),this._element.blur(),this._isShown=!1,this._element.classList.add($n),this._backdrop.hide(),this._queueCallback((()=>{this._element.classList.remove(Sn,$n),this._element.removeAttribute("aria-modal"),this._element.removeAttribute("role"),this._config.scroll||(new cn).reset(),N.trigger(this._element,Fn)}),this._element,!0)))}dispose(){this._backdrop.dispose(),this._focustrap.deactivate(),super.dispose()}_initializeBackDrop(){const t=Boolean(this._config.backdrop);return new Ui({className:"offcanvas-backdrop",isVisible:t,isAnimated:!0,rootElement:this._element.parentNode,clickCallback:t?()=>{"static"!==this._config.backdrop?this.hide():N.trigger(this._element,jn)}:null})}_initializeFocusTrap(){return new sn({trapElement:this._element})}_addEventListeners(){N.on(this._element,Bn,(t=>{"Escape"===t.key&&(this._config.keyboard?this.hide():N.trigger(this._element,jn))}))}static jQueryInterface(t){return this.each((function(){const e=qn.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t](this)}}))}}N.on(document,Wn,'[data-bs-toggle="offcanvas"]',(function(t){const e=z.getElementFromSelector(this);if(["A","AREA"].includes(this.tagName)&&t.preventDefault(),l(this))return;N.one(e,Fn,(()=>{a(this)&&this.focus()}));const i=z.findOne(In);i&&i!==e&&qn.getInstance(i).hide(),qn.getOrCreateInstance(e).toggle(this)})),N.on(window,Ln,(()=>{for(const t of z.find(In))qn.getOrCreateInstance(t).show()})),N.on(window,Hn,(()=>{for(const t of z.find("[aria-modal][class*=show][class*=offcanvas-]"))"fixed"!==getComputedStyle(t).position&&qn.getOrCreateInstance(t).hide()})),R(qn),m(qn);const Vn={"*":["class","dir","id","lang","role",/^aria-[\w-]*$/i],a:["target","href","title","rel"],area:[],b:[],br:[],col:[],code:[],div:[],em:[],hr:[],h1:[],h2:[],h3:[],h4:[],h5:[],h6:[],i:[],img:["src","srcset","alt","title","width","height"],li:[],ol:[],p:[],pre:[],s:[],small:[],span:[],sub:[],sup:[],strong:[],u:[],ul:[]},Kn=new Set(["background","cite","href","itemtype","longdesc","poster","src","xlink:href"]),Qn=/^(?!javascript:)(?:[a-z0-9+.-]+:|[^&:/?#]*(?:[/?#]|$))/i,Xn=(t,e)=>{const i=t.nodeName.toLowerCase();return e.includes(i)?!Kn.has(i)||Boolean(Qn.test(t.nodeValue)):e.filter((t=>t instanceof RegExp)).some((t=>t.test(i)))},Yn={allowList:Vn,content:{},extraClass:"",html:!1,sanitize:!0,sanitizeFn:null,template:"
"},Un={allowList:"object",content:"object",extraClass:"(string|function)",html:"boolean",sanitize:"boolean",sanitizeFn:"(null|function)",template:"string"},Gn={entry:"(string|element|function|null)",selector:"(string|element)"};class Jn extends H{constructor(t){super(),this._config=this._getConfig(t)}static get Default(){return Yn}static get DefaultType(){return Un}static get NAME(){return"TemplateFactory"}getContent(){return Object.values(this._config.content).map((t=>this._resolvePossibleFunction(t))).filter(Boolean)}hasContent(){return this.getContent().length>0}changeContent(t){return this._checkContent(t),this._config.content={...this._config.content,...t},this}toHtml(){const t=document.createElement("div");t.innerHTML=this._maybeSanitize(this._config.template);for(const[e,i]of Object.entries(this._config.content))this._setContent(t,i,e);const e=t.children[0],i=this._resolvePossibleFunction(this._config.extraClass);return i&&e.classList.add(...i.split(" ")),e}_typeCheckConfig(t){super._typeCheckConfig(t),this._checkContent(t.content)}_checkContent(t){for(const[e,i]of Object.entries(t))super._typeCheckConfig({selector:e,entry:i},Gn)}_setContent(t,e,i){const n=z.findOne(i,t);n&&((e=this._resolvePossibleFunction(e))?o(e)?this._putElementInTemplate(r(e),n):this._config.html?n.innerHTML=this._maybeSanitize(e):n.textContent=e:n.remove())}_maybeSanitize(t){return this._config.sanitize?function(t,e,i){if(!t.length)return t;if(i&&"function"==typeof i)return i(t);const n=(new window.DOMParser).parseFromString(t,"text/html"),s=[].concat(...n.body.querySelectorAll("*"));for(const t of s){const i=t.nodeName.toLowerCase();if(!Object.keys(e).includes(i)){t.remove();continue}const n=[].concat(...t.attributes),s=[].concat(e["*"]||[],e[i]||[]);for(const e of n)Xn(e,s)||t.removeAttribute(e.nodeName)}return n.body.innerHTML}(t,this._config.allowList,this._config.sanitizeFn):t}_resolvePossibleFunction(t){return g(t,[this])}_putElementInTemplate(t,e){if(this._config.html)return e.innerHTML="",void e.append(t);e.textContent=t.textContent}}const Zn=new Set(["sanitize","allowList","sanitizeFn"]),ts="fade",es="show",is=".modal",ns="hide.bs.modal",ss="hover",os="focus",rs={AUTO:"auto",TOP:"top",RIGHT:p()?"left":"right",BOTTOM:"bottom",LEFT:p()?"right":"left"},as={allowList:Vn,animation:!0,boundary:"clippingParents",container:!1,customClass:"",delay:0,fallbackPlacements:["top","right","bottom","left"],html:!1,offset:[0,6],placement:"top",popperConfig:null,sanitize:!0,sanitizeFn:null,selector:!1,template:'',title:"",trigger:"hover focus"},ls={allowList:"object",animation:"boolean",boundary:"(string|element)",container:"(string|element|boolean)",customClass:"(string|function)",delay:"(number|object)",fallbackPlacements:"array",html:"boolean",offset:"(array|string|function)",placement:"(string|function)",popperConfig:"(null|object|function)",sanitize:"boolean",sanitizeFn:"(null|function)",selector:"(string|boolean)",template:"string",title:"(string|element|function)",trigger:"string"};class cs extends W{constructor(t,e){if(void 0===vi)throw new TypeError("Bootstrap's tooltips require Popper (https://popper.js.org)");super(t,e),this._isEnabled=!0,this._timeout=0,this._isHovered=null,this._activeTrigger={},this._popper=null,this._templateFactory=null,this._newContent=null,this.tip=null,this._setListeners(),this._config.selector||this._fixTitle()}static get Default(){return as}static get DefaultType(){return ls}static get NAME(){return"tooltip"}enable(){this._isEnabled=!0}disable(){this._isEnabled=!1}toggleEnabled(){this._isEnabled=!this._isEnabled}toggle(){this._isEnabled&&(this._activeTrigger.click=!this._activeTrigger.click,this._isShown()?this._leave():this._enter())}dispose(){clearTimeout(this._timeout),N.off(this._element.closest(is),ns,this._hideModalHandler),this._element.getAttribute("data-bs-original-title")&&this._element.setAttribute("title",this._element.getAttribute("data-bs-original-title")),this._disposePopper(),super.dispose()}show(){if("none"===this._element.style.display)throw new Error("Please use show on visible elements");if(!this._isWithContent()||!this._isEnabled)return;const t=N.trigger(this._element,this.constructor.eventName("show")),e=(c(this._element)||this._element.ownerDocument.documentElement).contains(this._element);if(t.defaultPrevented||!e)return;this._disposePopper();const i=this._getTipElement();this._element.setAttribute("aria-describedby",i.getAttribute("id"));const{container:n}=this._config;if(this._element.ownerDocument.documentElement.contains(this.tip)||(n.append(i),N.trigger(this._element,this.constructor.eventName("inserted"))),this._popper=this._createPopper(i),i.classList.add(es),"ontouchstart"in document.documentElement)for(const t of[].concat(...document.body.children))N.on(t,"mouseover",h);this._queueCallback((()=>{N.trigger(this._element,this.constructor.eventName("shown")),!1===this._isHovered&&this._leave(),this._isHovered=!1}),this.tip,this._isAnimated())}hide(){if(this._isShown()&&!N.trigger(this._element,this.constructor.eventName("hide")).defaultPrevented){if(this._getTipElement().classList.remove(es),"ontouchstart"in document.documentElement)for(const t of[].concat(...document.body.children))N.off(t,"mouseover",h);this._activeTrigger.click=!1,this._activeTrigger[os]=!1,this._activeTrigger[ss]=!1,this._isHovered=null,this._queueCallback((()=>{this._isWithActiveTrigger()||(this._isHovered||this._disposePopper(),this._element.removeAttribute("aria-describedby"),N.trigger(this._element,this.constructor.eventName("hidden")))}),this.tip,this._isAnimated())}}update(){this._popper&&this._popper.update()}_isWithContent(){return Boolean(this._getTitle())}_getTipElement(){return this.tip||(this.tip=this._createTipElement(this._newContent||this._getContentForTemplate())),this.tip}_createTipElement(t){const e=this._getTemplateFactory(t).toHtml();if(!e)return null;e.classList.remove(ts,es),e.classList.add(`bs-${this.constructor.NAME}-auto`);const i=(t=>{do{t+=Math.floor(1e6*Math.random())}while(document.getElementById(t));return t})(this.constructor.NAME).toString();return e.setAttribute("id",i),this._isAnimated()&&e.classList.add(ts),e}setContent(t){this._newContent=t,this._isShown()&&(this._disposePopper(),this.show())}_getTemplateFactory(t){return this._templateFactory?this._templateFactory.changeContent(t):this._templateFactory=new Jn({...this._config,content:t,extraClass:this._resolvePossibleFunction(this._config.customClass)}),this._templateFactory}_getContentForTemplate(){return{".tooltip-inner":this._getTitle()}}_getTitle(){return this._resolvePossibleFunction(this._config.title)||this._element.getAttribute("data-bs-original-title")}_initializeOnDelegatedTarget(t){return this.constructor.getOrCreateInstance(t.delegateTarget,this._getDelegateConfig())}_isAnimated(){return this._config.animation||this.tip&&this.tip.classList.contains(ts)}_isShown(){return this.tip&&this.tip.classList.contains(es)}_createPopper(t){const e=g(this._config.placement,[this,t,this._element]),i=rs[e.toUpperCase()];return bi(this._element,t,this._getPopperConfig(i))}_getOffset(){const{offset:t}=this._config;return"string"==typeof t?t.split(",").map((t=>Number.parseInt(t,10))):"function"==typeof t?e=>t(e,this._element):t}_resolvePossibleFunction(t){return g(t,[this._element])}_getPopperConfig(t){const e={placement:t,modifiers:[{name:"flip",options:{fallbackPlacements:this._config.fallbackPlacements}},{name:"offset",options:{offset:this._getOffset()}},{name:"preventOverflow",options:{boundary:this._config.boundary}},{name:"arrow",options:{element:`.${this.constructor.NAME}-arrow`}},{name:"preSetPlacement",enabled:!0,phase:"beforeMain",fn:t=>{this._getTipElement().setAttribute("data-popper-placement",t.state.placement)}}]};return{...e,...g(this._config.popperConfig,[e])}}_setListeners(){const t=this._config.trigger.split(" ");for(const e of t)if("click"===e)N.on(this._element,this.constructor.eventName("click"),this._config.selector,(t=>{this._initializeOnDelegatedTarget(t).toggle()}));else if("manual"!==e){const t=e===ss?this.constructor.eventName("mouseenter"):this.constructor.eventName("focusin"),i=e===ss?this.constructor.eventName("mouseleave"):this.constructor.eventName("focusout");N.on(this._element,t,this._config.selector,(t=>{const e=this._initializeOnDelegatedTarget(t);e._activeTrigger["focusin"===t.type?os:ss]=!0,e._enter()})),N.on(this._element,i,this._config.selector,(t=>{const e=this._initializeOnDelegatedTarget(t);e._activeTrigger["focusout"===t.type?os:ss]=e._element.contains(t.relatedTarget),e._leave()}))}this._hideModalHandler=()=>{this._element&&this.hide()},N.on(this._element.closest(is),ns,this._hideModalHandler)}_fixTitle(){const t=this._element.getAttribute("title");t&&(this._element.getAttribute("aria-label")||this._element.textContent.trim()||this._element.setAttribute("aria-label",t),this._element.setAttribute("data-bs-original-title",t),this._element.removeAttribute("title"))}_enter(){this._isShown()||this._isHovered?this._isHovered=!0:(this._isHovered=!0,this._setTimeout((()=>{this._isHovered&&this.show()}),this._config.delay.show))}_leave(){this._isWithActiveTrigger()||(this._isHovered=!1,this._setTimeout((()=>{this._isHovered||this.hide()}),this._config.delay.hide))}_setTimeout(t,e){clearTimeout(this._timeout),this._timeout=setTimeout(t,e)}_isWithActiveTrigger(){return Object.values(this._activeTrigger).includes(!0)}_getConfig(t){const e=F.getDataAttributes(this._element);for(const t of Object.keys(e))Zn.has(t)&&delete e[t];return t={...e,..."object"==typeof t&&t?t:{}},t=this._mergeConfigObj(t),t=this._configAfterMerge(t),this._typeCheckConfig(t),t}_configAfterMerge(t){return t.container=!1===t.container?document.body:r(t.container),"number"==typeof t.delay&&(t.delay={show:t.delay,hide:t.delay}),"number"==typeof t.title&&(t.title=t.title.toString()),"number"==typeof t.content&&(t.content=t.content.toString()),t}_getDelegateConfig(){const t={};for(const[e,i]of Object.entries(this._config))this.constructor.Default[e]!==i&&(t[e]=i);return t.selector=!1,t.trigger="manual",t}_disposePopper(){this._popper&&(this._popper.destroy(),this._popper=null),this.tip&&(this.tip.remove(),this.tip=null)}static jQueryInterface(t){return this.each((function(){const e=cs.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}}))}}m(cs);const hs={...cs.Default,content:"",offset:[0,8],placement:"right",template:'',trigger:"click"},ds={...cs.DefaultType,content:"(null|string|element|function)"};class us extends cs{static get Default(){return hs}static get DefaultType(){return ds}static get NAME(){return"popover"}_isWithContent(){return this._getTitle()||this._getContent()}_getContentForTemplate(){return{".popover-header":this._getTitle(),".popover-body":this._getContent()}}_getContent(){return this._resolvePossibleFunction(this._config.content)}static jQueryInterface(t){return this.each((function(){const e=us.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}}))}}m(us);const fs=".bs.scrollspy",ps=`activate${fs}`,ms=`click${fs}`,gs=`load${fs}.data-api`,_s="active",bs="[href]",vs=".nav-link",ys=`${vs}, .nav-item > ${vs}, .list-group-item`,ws={offset:null,rootMargin:"0px 0px -25%",smoothScroll:!1,target:null,threshold:[.1,.5,1]},As={offset:"(number|null)",rootMargin:"string",smoothScroll:"boolean",target:"element",threshold:"array"};class Es extends W{constructor(t,e){super(t,e),this._targetLinks=new Map,this._observableSections=new Map,this._rootElement="visible"===getComputedStyle(this._element).overflowY?null:this._element,this._activeTarget=null,this._observer=null,this._previousScrollData={visibleEntryTop:0,parentScrollTop:0},this.refresh()}static get Default(){return ws}static get DefaultType(){return As}static get NAME(){return"scrollspy"}refresh(){this._initializeTargetsAndObservables(),this._maybeEnableSmoothScroll(),this._observer?this._observer.disconnect():this._observer=this._getNewObserver();for(const t of this._observableSections.values())this._observer.observe(t)}dispose(){this._observer.disconnect(),super.dispose()}_configAfterMerge(t){return t.target=r(t.target)||document.body,t.rootMargin=t.offset?`${t.offset}px 0px -30%`:t.rootMargin,"string"==typeof t.threshold&&(t.threshold=t.threshold.split(",").map((t=>Number.parseFloat(t)))),t}_maybeEnableSmoothScroll(){this._config.smoothScroll&&(N.off(this._config.target,ms),N.on(this._config.target,ms,bs,(t=>{const e=this._observableSections.get(t.target.hash);if(e){t.preventDefault();const i=this._rootElement||window,n=e.offsetTop-this._element.offsetTop;if(i.scrollTo)return void i.scrollTo({top:n,behavior:"smooth"});i.scrollTop=n}})))}_getNewObserver(){const t={root:this._rootElement,threshold:this._config.threshold,rootMargin:this._config.rootMargin};return new IntersectionObserver((t=>this._observerCallback(t)),t)}_observerCallback(t){const e=t=>this._targetLinks.get(`#${t.target.id}`),i=t=>{this._previousScrollData.visibleEntryTop=t.target.offsetTop,this._process(e(t))},n=(this._rootElement||document.documentElement).scrollTop,s=n>=this._previousScrollData.parentScrollTop;this._previousScrollData.parentScrollTop=n;for(const o of t){if(!o.isIntersecting){this._activeTarget=null,this._clearActiveClass(e(o));continue}const t=o.target.offsetTop>=this._previousScrollData.visibleEntryTop;if(s&&t){if(i(o),!n)return}else s||t||i(o)}}_initializeTargetsAndObservables(){this._targetLinks=new Map,this._observableSections=new Map;const t=z.find(bs,this._config.target);for(const e of t){if(!e.hash||l(e))continue;const t=z.findOne(decodeURI(e.hash),this._element);a(t)&&(this._targetLinks.set(decodeURI(e.hash),e),this._observableSections.set(e.hash,t))}}_process(t){this._activeTarget!==t&&(this._clearActiveClass(this._config.target),this._activeTarget=t,t.classList.add(_s),this._activateParents(t),N.trigger(this._element,ps,{relatedTarget:t}))}_activateParents(t){if(t.classList.contains("dropdown-item"))z.findOne(".dropdown-toggle",t.closest(".dropdown")).classList.add(_s);else for(const e of z.parents(t,".nav, .list-group"))for(const t of z.prev(e,ys))t.classList.add(_s)}_clearActiveClass(t){t.classList.remove(_s);const e=z.find(`${bs}.${_s}`,t);for(const t of e)t.classList.remove(_s)}static jQueryInterface(t){return this.each((function(){const e=Es.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t]()}}))}}N.on(window,gs,(()=>{for(const t of z.find('[data-bs-spy="scroll"]'))Es.getOrCreateInstance(t)})),m(Es);const Ts=".bs.tab",Cs=`hide${Ts}`,Os=`hidden${Ts}`,xs=`show${Ts}`,ks=`shown${Ts}`,Ls=`click${Ts}`,Ss=`keydown${Ts}`,Ds=`load${Ts}`,$s="ArrowLeft",Is="ArrowRight",Ns="ArrowUp",Ps="ArrowDown",Ms="Home",js="End",Fs="active",Hs="fade",Ws="show",Bs=".dropdown-toggle",zs=`:not(${Bs})`,Rs='[data-bs-toggle="tab"], [data-bs-toggle="pill"], [data-bs-toggle="list"]',qs=`.nav-link${zs}, .list-group-item${zs}, [role="tab"]${zs}, ${Rs}`,Vs=`.${Fs}[data-bs-toggle="tab"], .${Fs}[data-bs-toggle="pill"], .${Fs}[data-bs-toggle="list"]`;class Ks extends W{constructor(t){super(t),this._parent=this._element.closest('.list-group, .nav, [role="tablist"]'),this._parent&&(this._setInitialAttributes(this._parent,this._getChildren()),N.on(this._element,Ss,(t=>this._keydown(t))))}static get NAME(){return"tab"}show(){const t=this._element;if(this._elemIsActive(t))return;const e=this._getActiveElem(),i=e?N.trigger(e,Cs,{relatedTarget:t}):null;N.trigger(t,xs,{relatedTarget:e}).defaultPrevented||i&&i.defaultPrevented||(this._deactivate(e,t),this._activate(t,e))}_activate(t,e){t&&(t.classList.add(Fs),this._activate(z.getElementFromSelector(t)),this._queueCallback((()=>{"tab"===t.getAttribute("role")?(t.removeAttribute("tabindex"),t.setAttribute("aria-selected",!0),this._toggleDropDown(t,!0),N.trigger(t,ks,{relatedTarget:e})):t.classList.add(Ws)}),t,t.classList.contains(Hs)))}_deactivate(t,e){t&&(t.classList.remove(Fs),t.blur(),this._deactivate(z.getElementFromSelector(t)),this._queueCallback((()=>{"tab"===t.getAttribute("role")?(t.setAttribute("aria-selected",!1),t.setAttribute("tabindex","-1"),this._toggleDropDown(t,!1),N.trigger(t,Os,{relatedTarget:e})):t.classList.remove(Ws)}),t,t.classList.contains(Hs)))}_keydown(t){if(![$s,Is,Ns,Ps,Ms,js].includes(t.key))return;t.stopPropagation(),t.preventDefault();const e=this._getChildren().filter((t=>!l(t)));let i;if([Ms,js].includes(t.key))i=e[t.key===Ms?0:e.length-1];else{const n=[Is,Ps].includes(t.key);i=b(e,t.target,n,!0)}i&&(i.focus({preventScroll:!0}),Ks.getOrCreateInstance(i).show())}_getChildren(){return z.find(qs,this._parent)}_getActiveElem(){return this._getChildren().find((t=>this._elemIsActive(t)))||null}_setInitialAttributes(t,e){this._setAttributeIfNotExists(t,"role","tablist");for(const t of e)this._setInitialAttributesOnChild(t)}_setInitialAttributesOnChild(t){t=this._getInnerElement(t);const e=this._elemIsActive(t),i=this._getOuterElement(t);t.setAttribute("aria-selected",e),i!==t&&this._setAttributeIfNotExists(i,"role","presentation"),e||t.setAttribute("tabindex","-1"),this._setAttributeIfNotExists(t,"role","tab"),this._setInitialAttributesOnTargetPanel(t)}_setInitialAttributesOnTargetPanel(t){const e=z.getElementFromSelector(t);e&&(this._setAttributeIfNotExists(e,"role","tabpanel"),t.id&&this._setAttributeIfNotExists(e,"aria-labelledby",`${t.id}`))}_toggleDropDown(t,e){const i=this._getOuterElement(t);if(!i.classList.contains("dropdown"))return;const n=(t,n)=>{const s=z.findOne(t,i);s&&s.classList.toggle(n,e)};n(Bs,Fs),n(".dropdown-menu",Ws),i.setAttribute("aria-expanded",e)}_setAttributeIfNotExists(t,e,i){t.hasAttribute(e)||t.setAttribute(e,i)}_elemIsActive(t){return t.classList.contains(Fs)}_getInnerElement(t){return t.matches(qs)?t:z.findOne(qs,t)}_getOuterElement(t){return t.closest(".nav-item, .list-group-item")||t}static jQueryInterface(t){return this.each((function(){const e=Ks.getOrCreateInstance(this);if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t]()}}))}}N.on(document,Ls,Rs,(function(t){["A","AREA"].includes(this.tagName)&&t.preventDefault(),l(this)||Ks.getOrCreateInstance(this).show()})),N.on(window,Ds,(()=>{for(const t of z.find(Vs))Ks.getOrCreateInstance(t)})),m(Ks);const Qs=".bs.toast",Xs=`mouseover${Qs}`,Ys=`mouseout${Qs}`,Us=`focusin${Qs}`,Gs=`focusout${Qs}`,Js=`hide${Qs}`,Zs=`hidden${Qs}`,to=`show${Qs}`,eo=`shown${Qs}`,io="hide",no="show",so="showing",oo={animation:"boolean",autohide:"boolean",delay:"number"},ro={animation:!0,autohide:!0,delay:5e3};class ao extends W{constructor(t,e){super(t,e),this._timeout=null,this._hasMouseInteraction=!1,this._hasKeyboardInteraction=!1,this._setListeners()}static get Default(){return ro}static get DefaultType(){return oo}static get NAME(){return"toast"}show(){N.trigger(this._element,to).defaultPrevented||(this._clearTimeout(),this._config.animation&&this._element.classList.add("fade"),this._element.classList.remove(io),d(this._element),this._element.classList.add(no,so),this._queueCallback((()=>{this._element.classList.remove(so),N.trigger(this._element,eo),this._maybeScheduleHide()}),this._element,this._config.animation))}hide(){this.isShown()&&(N.trigger(this._element,Js).defaultPrevented||(this._element.classList.add(so),this._queueCallback((()=>{this._element.classList.add(io),this._element.classList.remove(so,no),N.trigger(this._element,Zs)}),this._element,this._config.animation)))}dispose(){this._clearTimeout(),this.isShown()&&this._element.classList.remove(no),super.dispose()}isShown(){return this._element.classList.contains(no)}_maybeScheduleHide(){this._config.autohide&&(this._hasMouseInteraction||this._hasKeyboardInteraction||(this._timeout=setTimeout((()=>{this.hide()}),this._config.delay)))}_onInteraction(t,e){switch(t.type){case"mouseover":case"mouseout":this._hasMouseInteraction=e;break;case"focusin":case"focusout":this._hasKeyboardInteraction=e}if(e)return void this._clearTimeout();const i=t.relatedTarget;this._element===i||this._element.contains(i)||this._maybeScheduleHide()}_setListeners(){N.on(this._element,Xs,(t=>this._onInteraction(t,!0))),N.on(this._element,Ys,(t=>this._onInteraction(t,!1))),N.on(this._element,Us,(t=>this._onInteraction(t,!0))),N.on(this._element,Gs,(t=>this._onInteraction(t,!1)))}_clearTimeout(){clearTimeout(this._timeout),this._timeout=null}static jQueryInterface(t){return this.each((function(){const e=ao.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t](this)}}))}}return R(ao),m(ao),{Alert:Q,Button:Y,Carousel:xt,Collapse:Bt,Dropdown:qi,Modal:On,Offcanvas:qn,Popover:us,ScrollSpy:Es,Tab:Ks,Toast:ao,Tooltip:cs}})); +//# sourceMappingURL=bootstrap.bundle.min.js.map \ No newline at end of file diff --git a/js/bootstrap.bundle.min.js.map b/js/bootstrap.bundle.min.js.map new file mode 100644 index 00000000..7cd8480d --- /dev/null +++ b/js/bootstrap.bundle.min.js.map @@ -0,0 +1 @@ +{"version":3,"names":["elementMap","Map","Data","set","element","key","instance","has","instanceMap","get","size","console","error","Array","from","keys","remove","delete","TRANSITION_END","parseSelector","selector","window","CSS","escape","replace","match","id","triggerTransitionEnd","dispatchEvent","Event","isElement","object","jquery","nodeType","getElement","length","document","querySelector","isVisible","getClientRects","elementIsVisible","getComputedStyle","getPropertyValue","closedDetails","closest","summary","parentNode","isDisabled","Node","ELEMENT_NODE","classList","contains","disabled","hasAttribute","getAttribute","findShadowRoot","documentElement","attachShadow","getRootNode","root","ShadowRoot","noop","reflow","offsetHeight","getjQuery","jQuery","body","DOMContentLoadedCallbacks","isRTL","dir","defineJQueryPlugin","plugin","callback","$","name","NAME","JQUERY_NO_CONFLICT","fn","jQueryInterface","Constructor","noConflict","readyState","addEventListener","push","execute","possibleCallback","args","defaultValue","executeAfterTransition","transitionElement","waitForTransition","emulatedDuration","transitionDuration","transitionDelay","floatTransitionDuration","Number","parseFloat","floatTransitionDelay","split","getTransitionDurationFromElement","called","handler","target","removeEventListener","setTimeout","getNextActiveElement","list","activeElement","shouldGetNext","isCycleAllowed","listLength","index","indexOf","Math","max","min","namespaceRegex","stripNameRegex","stripUidRegex","eventRegistry","uidEvent","customEvents","mouseenter","mouseleave","nativeEvents","Set","makeEventUid","uid","getElementEvents","findHandler","events","callable","delegationSelector","Object","values","find","event","normalizeParameters","originalTypeEvent","delegationFunction","isDelegated","typeEvent","getTypeEvent","addHandler","oneOff","wrapFunction","relatedTarget","delegateTarget","call","this","handlers","previousFunction","domElements","querySelectorAll","domElement","hydrateObj","EventHandler","off","type","apply","bootstrapDelegationHandler","bootstrapHandler","removeHandler","Boolean","removeNamespacedHandlers","namespace","storeElementEvent","handlerKey","entries","includes","on","one","inNamespace","isNamespace","startsWith","elementEvent","slice","keyHandlers","trigger","jQueryEvent","bubbles","nativeDispatch","defaultPrevented","isPropagationStopped","isImmediatePropagationStopped","isDefaultPrevented","evt","cancelable","preventDefault","obj","meta","value","_unused","defineProperty","configurable","normalizeData","toString","JSON","parse","decodeURIComponent","normalizeDataKey","chr","toLowerCase","Manipulator","setDataAttribute","setAttribute","removeDataAttribute","removeAttribute","getDataAttributes","attributes","bsKeys","dataset","filter","pureKey","charAt","getDataAttribute","Config","Default","DefaultType","Error","_getConfig","config","_mergeConfigObj","_configAfterMerge","_typeCheckConfig","jsonConfig","constructor","configTypes","property","expectedTypes","valueType","prototype","RegExp","test","TypeError","toUpperCase","BaseComponent","super","_element","_config","DATA_KEY","dispose","EVENT_KEY","propertyName","getOwnPropertyNames","_queueCallback","isAnimated","getInstance","getOrCreateInstance","VERSION","eventName","getSelector","hrefAttribute","trim","SelectorEngine","concat","Element","findOne","children","child","matches","parents","ancestor","prev","previous","previousElementSibling","next","nextElementSibling","focusableChildren","focusables","map","join","el","getSelectorFromElement","getElementFromSelector","getMultipleElementsFromSelector","enableDismissTrigger","component","method","clickEvent","tagName","EVENT_CLOSE","EVENT_CLOSED","Alert","close","_destroyElement","each","data","undefined","SELECTOR_DATA_TOGGLE","Button","toggle","button","EVENT_TOUCHSTART","EVENT_TOUCHMOVE","EVENT_TOUCHEND","EVENT_POINTERDOWN","EVENT_POINTERUP","endCallback","leftCallback","rightCallback","Swipe","isSupported","_deltaX","_supportPointerEvents","PointerEvent","_initEvents","_start","_eventIsPointerPenTouch","clientX","touches","_end","_handleSwipe","_move","absDeltaX","abs","direction","add","pointerType","navigator","maxTouchPoints","DATA_API_KEY","ORDER_NEXT","ORDER_PREV","DIRECTION_LEFT","DIRECTION_RIGHT","EVENT_SLIDE","EVENT_SLID","EVENT_KEYDOWN","EVENT_MOUSEENTER","EVENT_MOUSELEAVE","EVENT_DRAG_START","EVENT_LOAD_DATA_API","EVENT_CLICK_DATA_API","CLASS_NAME_CAROUSEL","CLASS_NAME_ACTIVE","SELECTOR_ACTIVE","SELECTOR_ITEM","SELECTOR_ACTIVE_ITEM","KEY_TO_DIRECTION","ArrowLeft","ArrowRight","interval","keyboard","pause","ride","touch","wrap","Carousel","_interval","_activeElement","_isSliding","touchTimeout","_swipeHelper","_indicatorsElement","_addEventListeners","cycle","_slide","nextWhenVisible","hidden","_clearInterval","_updateInterval","setInterval","_maybeEnableCycle","to","items","_getItems","activeIndex","_getItemIndex","_getActive","order","defaultInterval","_keydown","_addTouchEventListeners","img","swipeConfig","_directionToOrder","endCallBack","clearTimeout","_setActiveIndicatorElement","activeIndicator","newActiveIndicator","elementInterval","parseInt","isNext","nextElement","nextElementIndex","triggerEvent","_orderToDirection","isCycling","directionalClassName","orderClassName","completeCallBack","_isAnimated","clearInterval","carousel","slideIndex","carousels","EVENT_SHOW","EVENT_SHOWN","EVENT_HIDE","EVENT_HIDDEN","CLASS_NAME_SHOW","CLASS_NAME_COLLAPSE","CLASS_NAME_COLLAPSING","CLASS_NAME_DEEPER_CHILDREN","parent","Collapse","_isTransitioning","_triggerArray","toggleList","elem","filterElement","foundElement","_initializeChildren","_addAriaAndCollapsedClass","_isShown","hide","show","activeChildren","_getFirstLevelChildren","activeInstance","dimension","_getDimension","style","scrollSize","complete","getBoundingClientRect","selected","triggerArray","isOpen","top","bottom","right","left","auto","basePlacements","start","end","clippingParents","viewport","popper","reference","variationPlacements","reduce","acc","placement","placements","beforeRead","read","afterRead","beforeMain","main","afterMain","beforeWrite","write","afterWrite","modifierPhases","getNodeName","nodeName","getWindow","node","ownerDocument","defaultView","isHTMLElement","HTMLElement","isShadowRoot","applyStyles$1","enabled","phase","_ref","state","elements","forEach","styles","assign","effect","_ref2","initialStyles","position","options","strategy","margin","arrow","hasOwnProperty","attribute","requires","getBasePlacement","round","getUAString","uaData","userAgentData","brands","isArray","item","brand","version","userAgent","isLayoutViewport","includeScale","isFixedStrategy","clientRect","scaleX","scaleY","offsetWidth","width","height","visualViewport","addVisualOffsets","x","offsetLeft","y","offsetTop","getLayoutRect","rootNode","isSameNode","host","isTableElement","getDocumentElement","getParentNode","assignedSlot","getTrueOffsetParent","offsetParent","getOffsetParent","isFirefox","currentNode","css","transform","perspective","contain","willChange","getContainingBlock","getMainAxisFromPlacement","within","mathMax","mathMin","mergePaddingObject","paddingObject","expandToHashMap","hashMap","arrow$1","_state$modifiersData$","arrowElement","popperOffsets","modifiersData","basePlacement","axis","len","padding","rects","toPaddingObject","arrowRect","minProp","maxProp","endDiff","startDiff","arrowOffsetParent","clientSize","clientHeight","clientWidth","centerToReference","center","offset","axisProp","centerOffset","_options$element","requiresIfExists","getVariation","unsetSides","mapToStyles","_Object$assign2","popperRect","variation","offsets","gpuAcceleration","adaptive","roundOffsets","isFixed","_offsets$x","_offsets$y","_ref3","hasX","hasY","sideX","sideY","win","heightProp","widthProp","_Object$assign","commonStyles","_ref4","dpr","devicePixelRatio","roundOffsetsByDPR","computeStyles$1","_ref5","_options$gpuAccelerat","_options$adaptive","_options$roundOffsets","passive","eventListeners","_options$scroll","scroll","_options$resize","resize","scrollParents","scrollParent","update","hash","getOppositePlacement","matched","getOppositeVariationPlacement","getWindowScroll","scrollLeft","pageXOffset","scrollTop","pageYOffset","getWindowScrollBarX","isScrollParent","_getComputedStyle","overflow","overflowX","overflowY","getScrollParent","listScrollParents","_element$ownerDocumen","isBody","updatedList","rectToClientRect","rect","getClientRectFromMixedType","clippingParent","html","layoutViewport","getViewportRect","clientTop","clientLeft","getInnerBoundingClientRect","winScroll","scrollWidth","scrollHeight","getDocumentRect","computeOffsets","commonX","commonY","mainAxis","detectOverflow","_options","_options$placement","_options$strategy","_options$boundary","boundary","_options$rootBoundary","rootBoundary","_options$elementConte","elementContext","_options$altBoundary","altBoundary","_options$padding","altContext","clippingClientRect","mainClippingParents","clipperElement","getClippingParents","firstClippingParent","clippingRect","accRect","getClippingRect","contextElement","referenceClientRect","popperClientRect","elementClientRect","overflowOffsets","offsetData","multiply","computeAutoPlacement","flipVariations","_options$allowedAutoP","allowedAutoPlacements","allPlacements","allowedPlacements","overflows","sort","a","b","flip$1","_skip","_options$mainAxis","checkMainAxis","_options$altAxis","altAxis","checkAltAxis","specifiedFallbackPlacements","fallbackPlacements","_options$flipVariatio","preferredPlacement","oppositePlacement","getExpandedFallbackPlacements","referenceRect","checksMap","makeFallbackChecks","firstFittingPlacement","i","_basePlacement","isStartVariation","isVertical","mainVariationSide","altVariationSide","checks","every","check","_loop","_i","fittingPlacement","reset","getSideOffsets","preventedOffsets","isAnySideFullyClipped","some","side","hide$1","preventOverflow","referenceOverflow","popperAltOverflow","referenceClippingOffsets","popperEscapeOffsets","isReferenceHidden","hasPopperEscaped","offset$1","_options$offset","invertDistance","skidding","distance","distanceAndSkiddingToXY","_data$state$placement","popperOffsets$1","preventOverflow$1","_options$tether","tether","_options$tetherOffset","tetherOffset","isBasePlacement","tetherOffsetValue","normalizedTetherOffsetValue","offsetModifierState","_offsetModifierState$","mainSide","altSide","additive","minLen","maxLen","arrowPaddingObject","arrowPaddingMin","arrowPaddingMax","arrowLen","minOffset","maxOffset","clientOffset","offsetModifierValue","tetherMax","preventedOffset","_offsetModifierState$2","_mainSide","_altSide","_offset","_len","_min","_max","isOriginSide","_offsetModifierValue","_tetherMin","_tetherMax","_preventedOffset","v","withinMaxClamp","getCompositeRect","elementOrVirtualElement","isOffsetParentAnElement","offsetParentIsScaled","isElementScaled","modifiers","visited","result","modifier","dep","depModifier","DEFAULT_OPTIONS","areValidElements","arguments","_key","popperGenerator","generatorOptions","_generatorOptions","_generatorOptions$def","defaultModifiers","_generatorOptions$def2","defaultOptions","pending","orderedModifiers","effectCleanupFns","isDestroyed","setOptions","setOptionsAction","cleanupModifierEffects","merged","orderModifiers","current","existing","m","_ref$options","cleanupFn","forceUpdate","_state$elements","_state$orderedModifie","_state$orderedModifie2","Promise","resolve","then","destroy","onFirstUpdate","createPopper","computeStyles","applyStyles","flip","ARROW_UP_KEY","ARROW_DOWN_KEY","EVENT_KEYDOWN_DATA_API","EVENT_KEYUP_DATA_API","SELECTOR_DATA_TOGGLE_SHOWN","SELECTOR_MENU","PLACEMENT_TOP","PLACEMENT_TOPEND","PLACEMENT_BOTTOM","PLACEMENT_BOTTOMEND","PLACEMENT_RIGHT","PLACEMENT_LEFT","autoClose","display","popperConfig","Dropdown","_popper","_parent","_menu","_inNavbar","_detectNavbar","_createPopper","focus","_completeHide","Popper","referenceElement","_getPopperConfig","_getPlacement","parentDropdown","isEnd","_getOffset","popperData","defaultBsPopperConfig","_selectMenuItem","clearMenus","openToggles","context","composedPath","isMenuTarget","dataApiKeydownHandler","isInput","isEscapeEvent","isUpOrDownEvent","getToggleButton","stopPropagation","EVENT_MOUSEDOWN","className","clickCallback","rootElement","Backdrop","_isAppended","_append","_getElement","_emulateAnimation","backdrop","createElement","append","EVENT_FOCUSIN","EVENT_KEYDOWN_TAB","TAB_NAV_BACKWARD","autofocus","trapElement","FocusTrap","_isActive","_lastTabNavDirection","activate","_handleFocusin","_handleKeydown","deactivate","shiftKey","SELECTOR_FIXED_CONTENT","SELECTOR_STICKY_CONTENT","PROPERTY_PADDING","PROPERTY_MARGIN","ScrollBarHelper","getWidth","documentWidth","innerWidth","_disableOverFlow","_setElementAttributes","calculatedValue","_resetElementAttributes","isOverflowing","_saveInitialAttribute","styleProperty","scrollbarWidth","_applyManipulationCallback","setProperty","actualValue","removeProperty","callBack","sel","EVENT_HIDE_PREVENTED","EVENT_RESIZE","EVENT_CLICK_DISMISS","EVENT_MOUSEDOWN_DISMISS","EVENT_KEYDOWN_DISMISS","CLASS_NAME_OPEN","CLASS_NAME_STATIC","Modal","_dialog","_backdrop","_initializeBackDrop","_focustrap","_initializeFocusTrap","_scrollBar","_adjustDialog","_showElement","_hideModal","handleUpdate","modalBody","transitionComplete","_triggerBackdropTransition","event2","_resetAdjustments","isModalOverflowing","initialOverflowY","isBodyOverflowing","paddingLeft","paddingRight","showEvent","alreadyOpen","CLASS_NAME_SHOWING","CLASS_NAME_HIDING","OPEN_SELECTOR","Offcanvas","blur","completeCallback","DefaultAllowlist","area","br","col","code","div","em","hr","h1","h2","h3","h4","h5","h6","li","ol","p","pre","s","small","span","sub","sup","strong","u","ul","uriAttributes","SAFE_URL_PATTERN","allowedAttribute","allowedAttributeList","attributeName","nodeValue","attributeRegex","regex","allowList","content","extraClass","sanitize","sanitizeFn","template","DefaultContentType","entry","TemplateFactory","getContent","_resolvePossibleFunction","hasContent","changeContent","_checkContent","toHtml","templateWrapper","innerHTML","_maybeSanitize","text","_setContent","arg","templateElement","_putElementInTemplate","textContent","unsafeHtml","sanitizeFunction","createdDocument","DOMParser","parseFromString","elementName","attributeList","allowedAttributes","sanitizeHtml","DISALLOWED_ATTRIBUTES","CLASS_NAME_FADE","SELECTOR_MODAL","EVENT_MODAL_HIDE","TRIGGER_HOVER","TRIGGER_FOCUS","AttachmentMap","AUTO","TOP","RIGHT","BOTTOM","LEFT","animation","container","customClass","delay","title","Tooltip","_isEnabled","_timeout","_isHovered","_activeTrigger","_templateFactory","_newContent","tip","_setListeners","_fixTitle","enable","disable","toggleEnabled","click","_leave","_enter","_hideModalHandler","_disposePopper","_isWithContent","isInTheDom","_getTipElement","_isWithActiveTrigger","_getTitle","_createTipElement","_getContentForTemplate","_getTemplateFactory","tipId","prefix","floor","random","getElementById","getUID","setContent","_initializeOnDelegatedTarget","_getDelegateConfig","attachment","triggers","eventIn","eventOut","_setTimeout","timeout","dataAttributes","dataAttribute","Popover","_getContent","EVENT_ACTIVATE","EVENT_CLICK","SELECTOR_TARGET_LINKS","SELECTOR_NAV_LINKS","SELECTOR_LINK_ITEMS","rootMargin","smoothScroll","threshold","ScrollSpy","_targetLinks","_observableSections","_rootElement","_activeTarget","_observer","_previousScrollData","visibleEntryTop","parentScrollTop","refresh","_initializeTargetsAndObservables","_maybeEnableSmoothScroll","disconnect","_getNewObserver","section","observe","observableSection","scrollTo","behavior","IntersectionObserver","_observerCallback","targetElement","_process","userScrollsDown","isIntersecting","_clearActiveClass","entryIsLowerThanPrevious","targetLinks","anchor","decodeURI","_activateParents","listGroup","activeNodes","spy","ARROW_LEFT_KEY","ARROW_RIGHT_KEY","HOME_KEY","END_KEY","SELECTOR_DROPDOWN_TOGGLE","NOT_SELECTOR_DROPDOWN_TOGGLE","SELECTOR_INNER_ELEM","SELECTOR_DATA_TOGGLE_ACTIVE","Tab","_setInitialAttributes","_getChildren","innerElem","_elemIsActive","active","_getActiveElem","hideEvent","_deactivate","_activate","relatedElem","_toggleDropDown","nextActiveElement","preventScroll","_setAttributeIfNotExists","_setInitialAttributesOnChild","_getInnerElement","isActive","outerElem","_getOuterElement","_setInitialAttributesOnTargetPanel","open","EVENT_MOUSEOVER","EVENT_MOUSEOUT","EVENT_FOCUSOUT","CLASS_NAME_HIDE","autohide","Toast","_hasMouseInteraction","_hasKeyboardInteraction","_clearTimeout","_maybeScheduleHide","isShown","_onInteraction","isInteracting"],"sources":["../../js/src/dom/data.js","../../js/src/util/index.js","../../js/src/dom/event-handler.js","../../js/src/dom/manipulator.js","../../js/src/util/config.js","../../js/src/base-component.js","../../js/src/dom/selector-engine.js","../../js/src/util/component-functions.js","../../js/src/alert.js","../../js/src/button.js","../../js/src/util/swipe.js","../../js/src/carousel.js","../../js/src/collapse.js","../../node_modules/@popperjs/core/lib/enums.js","../../node_modules/@popperjs/core/lib/dom-utils/getNodeName.js","../../node_modules/@popperjs/core/lib/dom-utils/getWindow.js","../../node_modules/@popperjs/core/lib/dom-utils/instanceOf.js","../../node_modules/@popperjs/core/lib/modifiers/applyStyles.js","../../node_modules/@popperjs/core/lib/utils/getBasePlacement.js","../../node_modules/@popperjs/core/lib/utils/math.js","../../node_modules/@popperjs/core/lib/utils/userAgent.js","../../node_modules/@popperjs/core/lib/dom-utils/isLayoutViewport.js","../../node_modules/@popperjs/core/lib/dom-utils/getBoundingClientRect.js","../../node_modules/@popperjs/core/lib/dom-utils/getLayoutRect.js","../../node_modules/@popperjs/core/lib/dom-utils/contains.js","../../node_modules/@popperjs/core/lib/dom-utils/getComputedStyle.js","../../node_modules/@popperjs/core/lib/dom-utils/isTableElement.js","../../node_modules/@popperjs/core/lib/dom-utils/getDocumentElement.js","../../node_modules/@popperjs/core/lib/dom-utils/getParentNode.js","../../node_modules/@popperjs/core/lib/dom-utils/getOffsetParent.js","../../node_modules/@popperjs/core/lib/utils/getMainAxisFromPlacement.js","../../node_modules/@popperjs/core/lib/utils/within.js","../../node_modules/@popperjs/core/lib/utils/mergePaddingObject.js","../../node_modules/@popperjs/core/lib/utils/getFreshSideObject.js","../../node_modules/@popperjs/core/lib/utils/expandToHashMap.js","../../node_modules/@popperjs/core/lib/modifiers/arrow.js","../../node_modules/@popperjs/core/lib/utils/getVariation.js","../../node_modules/@popperjs/core/lib/modifiers/computeStyles.js","../../node_modules/@popperjs/core/lib/modifiers/eventListeners.js","../../node_modules/@popperjs/core/lib/utils/getOppositePlacement.js","../../node_modules/@popperjs/core/lib/utils/getOppositeVariationPlacement.js","../../node_modules/@popperjs/core/lib/dom-utils/getWindowScroll.js","../../node_modules/@popperjs/core/lib/dom-utils/getWindowScrollBarX.js","../../node_modules/@popperjs/core/lib/dom-utils/isScrollParent.js","../../node_modules/@popperjs/core/lib/dom-utils/getScrollParent.js","../../node_modules/@popperjs/core/lib/dom-utils/listScrollParents.js","../../node_modules/@popperjs/core/lib/utils/rectToClientRect.js","../../node_modules/@popperjs/core/lib/dom-utils/getClippingRect.js","../../node_modules/@popperjs/core/lib/dom-utils/getViewportRect.js","../../node_modules/@popperjs/core/lib/dom-utils/getDocumentRect.js","../../node_modules/@popperjs/core/lib/utils/computeOffsets.js","../../node_modules/@popperjs/core/lib/utils/detectOverflow.js","../../node_modules/@popperjs/core/lib/utils/computeAutoPlacement.js","../../node_modules/@popperjs/core/lib/modifiers/flip.js","../../node_modules/@popperjs/core/lib/modifiers/hide.js","../../node_modules/@popperjs/core/lib/modifiers/offset.js","../../node_modules/@popperjs/core/lib/modifiers/popperOffsets.js","../../node_modules/@popperjs/core/lib/modifiers/preventOverflow.js","../../node_modules/@popperjs/core/lib/utils/getAltAxis.js","../../node_modules/@popperjs/core/lib/dom-utils/getCompositeRect.js","../../node_modules/@popperjs/core/lib/dom-utils/getNodeScroll.js","../../node_modules/@popperjs/core/lib/dom-utils/getHTMLElementScroll.js","../../node_modules/@popperjs/core/lib/utils/orderModifiers.js","../../node_modules/@popperjs/core/lib/createPopper.js","../../node_modules/@popperjs/core/lib/utils/debounce.js","../../node_modules/@popperjs/core/lib/utils/mergeByName.js","../../node_modules/@popperjs/core/lib/popper-lite.js","../../node_modules/@popperjs/core/lib/popper.js","../../js/src/dropdown.js","../../js/src/util/backdrop.js","../../js/src/util/focustrap.js","../../js/src/util/scrollbar.js","../../js/src/modal.js","../../js/src/offcanvas.js","../../js/src/util/sanitizer.js","../../js/src/util/template-factory.js","../../js/src/tooltip.js","../../js/src/popover.js","../../js/src/scrollspy.js","../../js/src/tab.js","../../js/src/toast.js","../../js/index.umd.js"],"sourcesContent":["/**\n * --------------------------------------------------------------------------\n * Bootstrap dom/data.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\n/**\n * Constants\n */\n\nconst elementMap = new Map()\n\nexport default {\n set(element, key, instance) {\n if (!elementMap.has(element)) {\n elementMap.set(element, new Map())\n }\n\n const instanceMap = elementMap.get(element)\n\n // make it clear we only want one instance per element\n // can be removed later when multiple key/instances are fine to be used\n if (!instanceMap.has(key) && instanceMap.size !== 0) {\n // eslint-disable-next-line no-console\n console.error(`Bootstrap doesn't allow more than one instance per element. Bound instance: ${Array.from(instanceMap.keys())[0]}.`)\n return\n }\n\n instanceMap.set(key, instance)\n },\n\n get(element, key) {\n if (elementMap.has(element)) {\n return elementMap.get(element).get(key) || null\n }\n\n return null\n },\n\n remove(element, key) {\n if (!elementMap.has(element)) {\n return\n }\n\n const instanceMap = elementMap.get(element)\n\n instanceMap.delete(key)\n\n // free up element references if there are no instances left for an element\n if (instanceMap.size === 0) {\n elementMap.delete(element)\n }\n }\n}\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap util/index.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nconst MAX_UID = 1_000_000\nconst MILLISECONDS_MULTIPLIER = 1000\nconst TRANSITION_END = 'transitionend'\n\n/**\n * Properly escape IDs selectors to handle weird IDs\n * @param {string} selector\n * @returns {string}\n */\nconst parseSelector = selector => {\n if (selector && window.CSS && window.CSS.escape) {\n // document.querySelector needs escaping to handle IDs (html5+) containing for instance /\n selector = selector.replace(/#([^\\s\"#']+)/g, (match, id) => `#${CSS.escape(id)}`)\n }\n\n return selector\n}\n\n// Shout-out Angus Croll (https://goo.gl/pxwQGp)\nconst toType = object => {\n if (object === null || object === undefined) {\n return `${object}`\n }\n\n return Object.prototype.toString.call(object).match(/\\s([a-z]+)/i)[1].toLowerCase()\n}\n\n/**\n * Public Util API\n */\n\nconst getUID = prefix => {\n do {\n prefix += Math.floor(Math.random() * MAX_UID)\n } while (document.getElementById(prefix))\n\n return prefix\n}\n\nconst getTransitionDurationFromElement = element => {\n if (!element) {\n return 0\n }\n\n // Get transition-duration of the element\n let { transitionDuration, transitionDelay } = window.getComputedStyle(element)\n\n const floatTransitionDuration = Number.parseFloat(transitionDuration)\n const floatTransitionDelay = Number.parseFloat(transitionDelay)\n\n // Return 0 if element or transition duration is not found\n if (!floatTransitionDuration && !floatTransitionDelay) {\n return 0\n }\n\n // If multiple durations are defined, take the first\n transitionDuration = transitionDuration.split(',')[0]\n transitionDelay = transitionDelay.split(',')[0]\n\n return (Number.parseFloat(transitionDuration) + Number.parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER\n}\n\nconst triggerTransitionEnd = element => {\n element.dispatchEvent(new Event(TRANSITION_END))\n}\n\nconst isElement = object => {\n if (!object || typeof object !== 'object') {\n return false\n }\n\n if (typeof object.jquery !== 'undefined') {\n object = object[0]\n }\n\n return typeof object.nodeType !== 'undefined'\n}\n\nconst getElement = object => {\n // it's a jQuery object or a node element\n if (isElement(object)) {\n return object.jquery ? object[0] : object\n }\n\n if (typeof object === 'string' && object.length > 0) {\n return document.querySelector(parseSelector(object))\n }\n\n return null\n}\n\nconst isVisible = element => {\n if (!isElement(element) || element.getClientRects().length === 0) {\n return false\n }\n\n const elementIsVisible = getComputedStyle(element).getPropertyValue('visibility') === 'visible'\n // Handle `details` element as its content may falsie appear visible when it is closed\n const closedDetails = element.closest('details:not([open])')\n\n if (!closedDetails) {\n return elementIsVisible\n }\n\n if (closedDetails !== element) {\n const summary = element.closest('summary')\n if (summary && summary.parentNode !== closedDetails) {\n return false\n }\n\n if (summary === null) {\n return false\n }\n }\n\n return elementIsVisible\n}\n\nconst isDisabled = element => {\n if (!element || element.nodeType !== Node.ELEMENT_NODE) {\n return true\n }\n\n if (element.classList.contains('disabled')) {\n return true\n }\n\n if (typeof element.disabled !== 'undefined') {\n return element.disabled\n }\n\n return element.hasAttribute('disabled') && element.getAttribute('disabled') !== 'false'\n}\n\nconst findShadowRoot = element => {\n if (!document.documentElement.attachShadow) {\n return null\n }\n\n // Can find the shadow root otherwise it'll return the document\n if (typeof element.getRootNode === 'function') {\n const root = element.getRootNode()\n return root instanceof ShadowRoot ? root : null\n }\n\n if (element instanceof ShadowRoot) {\n return element\n }\n\n // when we don't find a shadow root\n if (!element.parentNode) {\n return null\n }\n\n return findShadowRoot(element.parentNode)\n}\n\nconst noop = () => {}\n\n/**\n * Trick to restart an element's animation\n *\n * @param {HTMLElement} element\n * @return void\n *\n * @see https://www.charistheo.io/blog/2021/02/restart-a-css-animation-with-javascript/#restarting-a-css-animation\n */\nconst reflow = element => {\n element.offsetHeight // eslint-disable-line no-unused-expressions\n}\n\nconst getjQuery = () => {\n if (window.jQuery && !document.body.hasAttribute('data-bs-no-jquery')) {\n return window.jQuery\n }\n\n return null\n}\n\nconst DOMContentLoadedCallbacks = []\n\nconst onDOMContentLoaded = callback => {\n if (document.readyState === 'loading') {\n // add listener on the first call when the document is in loading state\n if (!DOMContentLoadedCallbacks.length) {\n document.addEventListener('DOMContentLoaded', () => {\n for (const callback of DOMContentLoadedCallbacks) {\n callback()\n }\n })\n }\n\n DOMContentLoadedCallbacks.push(callback)\n } else {\n callback()\n }\n}\n\nconst isRTL = () => document.documentElement.dir === 'rtl'\n\nconst defineJQueryPlugin = plugin => {\n onDOMContentLoaded(() => {\n const $ = getjQuery()\n /* istanbul ignore if */\n if ($) {\n const name = plugin.NAME\n const JQUERY_NO_CONFLICT = $.fn[name]\n $.fn[name] = plugin.jQueryInterface\n $.fn[name].Constructor = plugin\n $.fn[name].noConflict = () => {\n $.fn[name] = JQUERY_NO_CONFLICT\n return plugin.jQueryInterface\n }\n }\n })\n}\n\nconst execute = (possibleCallback, args = [], defaultValue = possibleCallback) => {\n return typeof possibleCallback === 'function' ? possibleCallback(...args) : defaultValue\n}\n\nconst executeAfterTransition = (callback, transitionElement, waitForTransition = true) => {\n if (!waitForTransition) {\n execute(callback)\n return\n }\n\n const durationPadding = 5\n const emulatedDuration = getTransitionDurationFromElement(transitionElement) + durationPadding\n\n let called = false\n\n const handler = ({ target }) => {\n if (target !== transitionElement) {\n return\n }\n\n called = true\n transitionElement.removeEventListener(TRANSITION_END, handler)\n execute(callback)\n }\n\n transitionElement.addEventListener(TRANSITION_END, handler)\n setTimeout(() => {\n if (!called) {\n triggerTransitionEnd(transitionElement)\n }\n }, emulatedDuration)\n}\n\n/**\n * Return the previous/next element of a list.\n *\n * @param {array} list The list of elements\n * @param activeElement The active element\n * @param shouldGetNext Choose to get next or previous element\n * @param isCycleAllowed\n * @return {Element|elem} The proper element\n */\nconst getNextActiveElement = (list, activeElement, shouldGetNext, isCycleAllowed) => {\n const listLength = list.length\n let index = list.indexOf(activeElement)\n\n // if the element does not exist in the list return an element\n // depending on the direction and if cycle is allowed\n if (index === -1) {\n return !shouldGetNext && isCycleAllowed ? list[listLength - 1] : list[0]\n }\n\n index += shouldGetNext ? 1 : -1\n\n if (isCycleAllowed) {\n index = (index + listLength) % listLength\n }\n\n return list[Math.max(0, Math.min(index, listLength - 1))]\n}\n\nexport {\n defineJQueryPlugin,\n execute,\n executeAfterTransition,\n findShadowRoot,\n getElement,\n getjQuery,\n getNextActiveElement,\n getTransitionDurationFromElement,\n getUID,\n isDisabled,\n isElement,\n isRTL,\n isVisible,\n noop,\n onDOMContentLoaded,\n parseSelector,\n reflow,\n triggerTransitionEnd,\n toType\n}\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap dom/event-handler.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport { getjQuery } from '../util/index.js'\n\n/**\n * Constants\n */\n\nconst namespaceRegex = /[^.]*(?=\\..*)\\.|.*/\nconst stripNameRegex = /\\..*/\nconst stripUidRegex = /::\\d+$/\nconst eventRegistry = {} // Events storage\nlet uidEvent = 1\nconst customEvents = {\n mouseenter: 'mouseover',\n mouseleave: 'mouseout'\n}\n\nconst nativeEvents = new Set([\n 'click',\n 'dblclick',\n 'mouseup',\n 'mousedown',\n 'contextmenu',\n 'mousewheel',\n 'DOMMouseScroll',\n 'mouseover',\n 'mouseout',\n 'mousemove',\n 'selectstart',\n 'selectend',\n 'keydown',\n 'keypress',\n 'keyup',\n 'orientationchange',\n 'touchstart',\n 'touchmove',\n 'touchend',\n 'touchcancel',\n 'pointerdown',\n 'pointermove',\n 'pointerup',\n 'pointerleave',\n 'pointercancel',\n 'gesturestart',\n 'gesturechange',\n 'gestureend',\n 'focus',\n 'blur',\n 'change',\n 'reset',\n 'select',\n 'submit',\n 'focusin',\n 'focusout',\n 'load',\n 'unload',\n 'beforeunload',\n 'resize',\n 'move',\n 'DOMContentLoaded',\n 'readystatechange',\n 'error',\n 'abort',\n 'scroll'\n])\n\n/**\n * Private methods\n */\n\nfunction makeEventUid(element, uid) {\n return (uid && `${uid}::${uidEvent++}`) || element.uidEvent || uidEvent++\n}\n\nfunction getElementEvents(element) {\n const uid = makeEventUid(element)\n\n element.uidEvent = uid\n eventRegistry[uid] = eventRegistry[uid] || {}\n\n return eventRegistry[uid]\n}\n\nfunction bootstrapHandler(element, fn) {\n return function handler(event) {\n hydrateObj(event, { delegateTarget: element })\n\n if (handler.oneOff) {\n EventHandler.off(element, event.type, fn)\n }\n\n return fn.apply(element, [event])\n }\n}\n\nfunction bootstrapDelegationHandler(element, selector, fn) {\n return function handler(event) {\n const domElements = element.querySelectorAll(selector)\n\n for (let { target } = event; target && target !== this; target = target.parentNode) {\n for (const domElement of domElements) {\n if (domElement !== target) {\n continue\n }\n\n hydrateObj(event, { delegateTarget: target })\n\n if (handler.oneOff) {\n EventHandler.off(element, event.type, selector, fn)\n }\n\n return fn.apply(target, [event])\n }\n }\n }\n}\n\nfunction findHandler(events, callable, delegationSelector = null) {\n return Object.values(events)\n .find(event => event.callable === callable && event.delegationSelector === delegationSelector)\n}\n\nfunction normalizeParameters(originalTypeEvent, handler, delegationFunction) {\n const isDelegated = typeof handler === 'string'\n // TODO: tooltip passes `false` instead of selector, so we need to check\n const callable = isDelegated ? delegationFunction : (handler || delegationFunction)\n let typeEvent = getTypeEvent(originalTypeEvent)\n\n if (!nativeEvents.has(typeEvent)) {\n typeEvent = originalTypeEvent\n }\n\n return [isDelegated, callable, typeEvent]\n}\n\nfunction addHandler(element, originalTypeEvent, handler, delegationFunction, oneOff) {\n if (typeof originalTypeEvent !== 'string' || !element) {\n return\n }\n\n let [isDelegated, callable, typeEvent] = normalizeParameters(originalTypeEvent, handler, delegationFunction)\n\n // in case of mouseenter or mouseleave wrap the handler within a function that checks for its DOM position\n // this prevents the handler from being dispatched the same way as mouseover or mouseout does\n if (originalTypeEvent in customEvents) {\n const wrapFunction = fn => {\n return function (event) {\n if (!event.relatedTarget || (event.relatedTarget !== event.delegateTarget && !event.delegateTarget.contains(event.relatedTarget))) {\n return fn.call(this, event)\n }\n }\n }\n\n callable = wrapFunction(callable)\n }\n\n const events = getElementEvents(element)\n const handlers = events[typeEvent] || (events[typeEvent] = {})\n const previousFunction = findHandler(handlers, callable, isDelegated ? handler : null)\n\n if (previousFunction) {\n previousFunction.oneOff = previousFunction.oneOff && oneOff\n\n return\n }\n\n const uid = makeEventUid(callable, originalTypeEvent.replace(namespaceRegex, ''))\n const fn = isDelegated ?\n bootstrapDelegationHandler(element, handler, callable) :\n bootstrapHandler(element, callable)\n\n fn.delegationSelector = isDelegated ? handler : null\n fn.callable = callable\n fn.oneOff = oneOff\n fn.uidEvent = uid\n handlers[uid] = fn\n\n element.addEventListener(typeEvent, fn, isDelegated)\n}\n\nfunction removeHandler(element, events, typeEvent, handler, delegationSelector) {\n const fn = findHandler(events[typeEvent], handler, delegationSelector)\n\n if (!fn) {\n return\n }\n\n element.removeEventListener(typeEvent, fn, Boolean(delegationSelector))\n delete events[typeEvent][fn.uidEvent]\n}\n\nfunction removeNamespacedHandlers(element, events, typeEvent, namespace) {\n const storeElementEvent = events[typeEvent] || {}\n\n for (const [handlerKey, event] of Object.entries(storeElementEvent)) {\n if (handlerKey.includes(namespace)) {\n removeHandler(element, events, typeEvent, event.callable, event.delegationSelector)\n }\n }\n}\n\nfunction getTypeEvent(event) {\n // allow to get the native events from namespaced events ('click.bs.button' --> 'click')\n event = event.replace(stripNameRegex, '')\n return customEvents[event] || event\n}\n\nconst EventHandler = {\n on(element, event, handler, delegationFunction) {\n addHandler(element, event, handler, delegationFunction, false)\n },\n\n one(element, event, handler, delegationFunction) {\n addHandler(element, event, handler, delegationFunction, true)\n },\n\n off(element, originalTypeEvent, handler, delegationFunction) {\n if (typeof originalTypeEvent !== 'string' || !element) {\n return\n }\n\n const [isDelegated, callable, typeEvent] = normalizeParameters(originalTypeEvent, handler, delegationFunction)\n const inNamespace = typeEvent !== originalTypeEvent\n const events = getElementEvents(element)\n const storeElementEvent = events[typeEvent] || {}\n const isNamespace = originalTypeEvent.startsWith('.')\n\n if (typeof callable !== 'undefined') {\n // Simplest case: handler is passed, remove that listener ONLY.\n if (!Object.keys(storeElementEvent).length) {\n return\n }\n\n removeHandler(element, events, typeEvent, callable, isDelegated ? handler : null)\n return\n }\n\n if (isNamespace) {\n for (const elementEvent of Object.keys(events)) {\n removeNamespacedHandlers(element, events, elementEvent, originalTypeEvent.slice(1))\n }\n }\n\n for (const [keyHandlers, event] of Object.entries(storeElementEvent)) {\n const handlerKey = keyHandlers.replace(stripUidRegex, '')\n\n if (!inNamespace || originalTypeEvent.includes(handlerKey)) {\n removeHandler(element, events, typeEvent, event.callable, event.delegationSelector)\n }\n }\n },\n\n trigger(element, event, args) {\n if (typeof event !== 'string' || !element) {\n return null\n }\n\n const $ = getjQuery()\n const typeEvent = getTypeEvent(event)\n const inNamespace = event !== typeEvent\n\n let jQueryEvent = null\n let bubbles = true\n let nativeDispatch = true\n let defaultPrevented = false\n\n if (inNamespace && $) {\n jQueryEvent = $.Event(event, args)\n\n $(element).trigger(jQueryEvent)\n bubbles = !jQueryEvent.isPropagationStopped()\n nativeDispatch = !jQueryEvent.isImmediatePropagationStopped()\n defaultPrevented = jQueryEvent.isDefaultPrevented()\n }\n\n const evt = hydrateObj(new Event(event, { bubbles, cancelable: true }), args)\n\n if (defaultPrevented) {\n evt.preventDefault()\n }\n\n if (nativeDispatch) {\n element.dispatchEvent(evt)\n }\n\n if (evt.defaultPrevented && jQueryEvent) {\n jQueryEvent.preventDefault()\n }\n\n return evt\n }\n}\n\nfunction hydrateObj(obj, meta = {}) {\n for (const [key, value] of Object.entries(meta)) {\n try {\n obj[key] = value\n } catch {\n Object.defineProperty(obj, key, {\n configurable: true,\n get() {\n return value\n }\n })\n }\n }\n\n return obj\n}\n\nexport default EventHandler\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap dom/manipulator.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nfunction normalizeData(value) {\n if (value === 'true') {\n return true\n }\n\n if (value === 'false') {\n return false\n }\n\n if (value === Number(value).toString()) {\n return Number(value)\n }\n\n if (value === '' || value === 'null') {\n return null\n }\n\n if (typeof value !== 'string') {\n return value\n }\n\n try {\n return JSON.parse(decodeURIComponent(value))\n } catch {\n return value\n }\n}\n\nfunction normalizeDataKey(key) {\n return key.replace(/[A-Z]/g, chr => `-${chr.toLowerCase()}`)\n}\n\nconst Manipulator = {\n setDataAttribute(element, key, value) {\n element.setAttribute(`data-bs-${normalizeDataKey(key)}`, value)\n },\n\n removeDataAttribute(element, key) {\n element.removeAttribute(`data-bs-${normalizeDataKey(key)}`)\n },\n\n getDataAttributes(element) {\n if (!element) {\n return {}\n }\n\n const attributes = {}\n const bsKeys = Object.keys(element.dataset).filter(key => key.startsWith('bs') && !key.startsWith('bsConfig'))\n\n for (const key of bsKeys) {\n let pureKey = key.replace(/^bs/, '')\n pureKey = pureKey.charAt(0).toLowerCase() + pureKey.slice(1, pureKey.length)\n attributes[pureKey] = normalizeData(element.dataset[key])\n }\n\n return attributes\n },\n\n getDataAttribute(element, key) {\n return normalizeData(element.getAttribute(`data-bs-${normalizeDataKey(key)}`))\n }\n}\n\nexport default Manipulator\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap util/config.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport Manipulator from '../dom/manipulator.js'\nimport { isElement, toType } from './index.js'\n\n/**\n * Class definition\n */\n\nclass Config {\n // Getters\n static get Default() {\n return {}\n }\n\n static get DefaultType() {\n return {}\n }\n\n static get NAME() {\n throw new Error('You have to implement the static method \"NAME\", for each component!')\n }\n\n _getConfig(config) {\n config = this._mergeConfigObj(config)\n config = this._configAfterMerge(config)\n this._typeCheckConfig(config)\n return config\n }\n\n _configAfterMerge(config) {\n return config\n }\n\n _mergeConfigObj(config, element) {\n const jsonConfig = isElement(element) ? Manipulator.getDataAttribute(element, 'config') : {} // try to parse\n\n return {\n ...this.constructor.Default,\n ...(typeof jsonConfig === 'object' ? jsonConfig : {}),\n ...(isElement(element) ? Manipulator.getDataAttributes(element) : {}),\n ...(typeof config === 'object' ? config : {})\n }\n }\n\n _typeCheckConfig(config, configTypes = this.constructor.DefaultType) {\n for (const [property, expectedTypes] of Object.entries(configTypes)) {\n const value = config[property]\n const valueType = isElement(value) ? 'element' : toType(value)\n\n if (!new RegExp(expectedTypes).test(valueType)) {\n throw new TypeError(\n `${this.constructor.NAME.toUpperCase()}: Option \"${property}\" provided type \"${valueType}\" but expected type \"${expectedTypes}\".`\n )\n }\n }\n }\n}\n\nexport default Config\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap base-component.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport Data from './dom/data.js'\nimport EventHandler from './dom/event-handler.js'\nimport Config from './util/config.js'\nimport { executeAfterTransition, getElement } from './util/index.js'\n\n/**\n * Constants\n */\n\nconst VERSION = '5.3.2'\n\n/**\n * Class definition\n */\n\nclass BaseComponent extends Config {\n constructor(element, config) {\n super()\n\n element = getElement(element)\n if (!element) {\n return\n }\n\n this._element = element\n this._config = this._getConfig(config)\n\n Data.set(this._element, this.constructor.DATA_KEY, this)\n }\n\n // Public\n dispose() {\n Data.remove(this._element, this.constructor.DATA_KEY)\n EventHandler.off(this._element, this.constructor.EVENT_KEY)\n\n for (const propertyName of Object.getOwnPropertyNames(this)) {\n this[propertyName] = null\n }\n }\n\n _queueCallback(callback, element, isAnimated = true) {\n executeAfterTransition(callback, element, isAnimated)\n }\n\n _getConfig(config) {\n config = this._mergeConfigObj(config, this._element)\n config = this._configAfterMerge(config)\n this._typeCheckConfig(config)\n return config\n }\n\n // Static\n static getInstance(element) {\n return Data.get(getElement(element), this.DATA_KEY)\n }\n\n static getOrCreateInstance(element, config = {}) {\n return this.getInstance(element) || new this(element, typeof config === 'object' ? config : null)\n }\n\n static get VERSION() {\n return VERSION\n }\n\n static get DATA_KEY() {\n return `bs.${this.NAME}`\n }\n\n static get EVENT_KEY() {\n return `.${this.DATA_KEY}`\n }\n\n static eventName(name) {\n return `${name}${this.EVENT_KEY}`\n }\n}\n\nexport default BaseComponent\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap dom/selector-engine.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport { isDisabled, isVisible, parseSelector } from '../util/index.js'\n\nconst getSelector = element => {\n let selector = element.getAttribute('data-bs-target')\n\n if (!selector || selector === '#') {\n let hrefAttribute = element.getAttribute('href')\n\n // The only valid content that could double as a selector are IDs or classes,\n // so everything starting with `#` or `.`. If a \"real\" URL is used as the selector,\n // `document.querySelector` will rightfully complain it is invalid.\n // See https://github.com/twbs/bootstrap/issues/32273\n if (!hrefAttribute || (!hrefAttribute.includes('#') && !hrefAttribute.startsWith('.'))) {\n return null\n }\n\n // Just in case some CMS puts out a full URL with the anchor appended\n if (hrefAttribute.includes('#') && !hrefAttribute.startsWith('#')) {\n hrefAttribute = `#${hrefAttribute.split('#')[1]}`\n }\n\n selector = hrefAttribute && hrefAttribute !== '#' ? parseSelector(hrefAttribute.trim()) : null\n }\n\n return selector\n}\n\nconst SelectorEngine = {\n find(selector, element = document.documentElement) {\n return [].concat(...Element.prototype.querySelectorAll.call(element, selector))\n },\n\n findOne(selector, element = document.documentElement) {\n return Element.prototype.querySelector.call(element, selector)\n },\n\n children(element, selector) {\n return [].concat(...element.children).filter(child => child.matches(selector))\n },\n\n parents(element, selector) {\n const parents = []\n let ancestor = element.parentNode.closest(selector)\n\n while (ancestor) {\n parents.push(ancestor)\n ancestor = ancestor.parentNode.closest(selector)\n }\n\n return parents\n },\n\n prev(element, selector) {\n let previous = element.previousElementSibling\n\n while (previous) {\n if (previous.matches(selector)) {\n return [previous]\n }\n\n previous = previous.previousElementSibling\n }\n\n return []\n },\n // TODO: this is now unused; remove later along with prev()\n next(element, selector) {\n let next = element.nextElementSibling\n\n while (next) {\n if (next.matches(selector)) {\n return [next]\n }\n\n next = next.nextElementSibling\n }\n\n return []\n },\n\n focusableChildren(element) {\n const focusables = [\n 'a',\n 'button',\n 'input',\n 'textarea',\n 'select',\n 'details',\n '[tabindex]',\n '[contenteditable=\"true\"]'\n ].map(selector => `${selector}:not([tabindex^=\"-\"])`).join(',')\n\n return this.find(focusables, element).filter(el => !isDisabled(el) && isVisible(el))\n },\n\n getSelectorFromElement(element) {\n const selector = getSelector(element)\n\n if (selector) {\n return SelectorEngine.findOne(selector) ? selector : null\n }\n\n return null\n },\n\n getElementFromSelector(element) {\n const selector = getSelector(element)\n\n return selector ? SelectorEngine.findOne(selector) : null\n },\n\n getMultipleElementsFromSelector(element) {\n const selector = getSelector(element)\n\n return selector ? SelectorEngine.find(selector) : []\n }\n}\n\nexport default SelectorEngine\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap util/component-functions.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport EventHandler from '../dom/event-handler.js'\nimport SelectorEngine from '../dom/selector-engine.js'\nimport { isDisabled } from './index.js'\n\nconst enableDismissTrigger = (component, method = 'hide') => {\n const clickEvent = `click.dismiss${component.EVENT_KEY}`\n const name = component.NAME\n\n EventHandler.on(document, clickEvent, `[data-bs-dismiss=\"${name}\"]`, function (event) {\n if (['A', 'AREA'].includes(this.tagName)) {\n event.preventDefault()\n }\n\n if (isDisabled(this)) {\n return\n }\n\n const target = SelectorEngine.getElementFromSelector(this) || this.closest(`.${name}`)\n const instance = component.getOrCreateInstance(target)\n\n // Method argument is left, for Alert and only, as it doesn't implement the 'hide' method\n instance[method]()\n })\n}\n\nexport {\n enableDismissTrigger\n}\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap alert.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport BaseComponent from './base-component.js'\nimport EventHandler from './dom/event-handler.js'\nimport { enableDismissTrigger } from './util/component-functions.js'\nimport { defineJQueryPlugin } from './util/index.js'\n\n/**\n * Constants\n */\n\nconst NAME = 'alert'\nconst DATA_KEY = 'bs.alert'\nconst EVENT_KEY = `.${DATA_KEY}`\n\nconst EVENT_CLOSE = `close${EVENT_KEY}`\nconst EVENT_CLOSED = `closed${EVENT_KEY}`\nconst CLASS_NAME_FADE = 'fade'\nconst CLASS_NAME_SHOW = 'show'\n\n/**\n * Class definition\n */\n\nclass Alert extends BaseComponent {\n // Getters\n static get NAME() {\n return NAME\n }\n\n // Public\n close() {\n const closeEvent = EventHandler.trigger(this._element, EVENT_CLOSE)\n\n if (closeEvent.defaultPrevented) {\n return\n }\n\n this._element.classList.remove(CLASS_NAME_SHOW)\n\n const isAnimated = this._element.classList.contains(CLASS_NAME_FADE)\n this._queueCallback(() => this._destroyElement(), this._element, isAnimated)\n }\n\n // Private\n _destroyElement() {\n this._element.remove()\n EventHandler.trigger(this._element, EVENT_CLOSED)\n this.dispose()\n }\n\n // Static\n static jQueryInterface(config) {\n return this.each(function () {\n const data = Alert.getOrCreateInstance(this)\n\n if (typeof config !== 'string') {\n return\n }\n\n if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {\n throw new TypeError(`No method named \"${config}\"`)\n }\n\n data[config](this)\n })\n }\n}\n\n/**\n * Data API implementation\n */\n\nenableDismissTrigger(Alert, 'close')\n\n/**\n * jQuery\n */\n\ndefineJQueryPlugin(Alert)\n\nexport default Alert\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap button.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport BaseComponent from './base-component.js'\nimport EventHandler from './dom/event-handler.js'\nimport { defineJQueryPlugin } from './util/index.js'\n\n/**\n * Constants\n */\n\nconst NAME = 'button'\nconst DATA_KEY = 'bs.button'\nconst EVENT_KEY = `.${DATA_KEY}`\nconst DATA_API_KEY = '.data-api'\n\nconst CLASS_NAME_ACTIVE = 'active'\nconst SELECTOR_DATA_TOGGLE = '[data-bs-toggle=\"button\"]'\nconst EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`\n\n/**\n * Class definition\n */\n\nclass Button extends BaseComponent {\n // Getters\n static get NAME() {\n return NAME\n }\n\n // Public\n toggle() {\n // Toggle class and sync the `aria-pressed` attribute with the return value of the `.toggle()` method\n this._element.setAttribute('aria-pressed', this._element.classList.toggle(CLASS_NAME_ACTIVE))\n }\n\n // Static\n static jQueryInterface(config) {\n return this.each(function () {\n const data = Button.getOrCreateInstance(this)\n\n if (config === 'toggle') {\n data[config]()\n }\n })\n }\n}\n\n/**\n * Data API implementation\n */\n\nEventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, event => {\n event.preventDefault()\n\n const button = event.target.closest(SELECTOR_DATA_TOGGLE)\n const data = Button.getOrCreateInstance(button)\n\n data.toggle()\n})\n\n/**\n * jQuery\n */\n\ndefineJQueryPlugin(Button)\n\nexport default Button\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap util/swipe.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport EventHandler from '../dom/event-handler.js'\nimport Config from './config.js'\nimport { execute } from './index.js'\n\n/**\n * Constants\n */\n\nconst NAME = 'swipe'\nconst EVENT_KEY = '.bs.swipe'\nconst EVENT_TOUCHSTART = `touchstart${EVENT_KEY}`\nconst EVENT_TOUCHMOVE = `touchmove${EVENT_KEY}`\nconst EVENT_TOUCHEND = `touchend${EVENT_KEY}`\nconst EVENT_POINTERDOWN = `pointerdown${EVENT_KEY}`\nconst EVENT_POINTERUP = `pointerup${EVENT_KEY}`\nconst POINTER_TYPE_TOUCH = 'touch'\nconst POINTER_TYPE_PEN = 'pen'\nconst CLASS_NAME_POINTER_EVENT = 'pointer-event'\nconst SWIPE_THRESHOLD = 40\n\nconst Default = {\n endCallback: null,\n leftCallback: null,\n rightCallback: null\n}\n\nconst DefaultType = {\n endCallback: '(function|null)',\n leftCallback: '(function|null)',\n rightCallback: '(function|null)'\n}\n\n/**\n * Class definition\n */\n\nclass Swipe extends Config {\n constructor(element, config) {\n super()\n this._element = element\n\n if (!element || !Swipe.isSupported()) {\n return\n }\n\n this._config = this._getConfig(config)\n this._deltaX = 0\n this._supportPointerEvents = Boolean(window.PointerEvent)\n this._initEvents()\n }\n\n // Getters\n static get Default() {\n return Default\n }\n\n static get DefaultType() {\n return DefaultType\n }\n\n static get NAME() {\n return NAME\n }\n\n // Public\n dispose() {\n EventHandler.off(this._element, EVENT_KEY)\n }\n\n // Private\n _start(event) {\n if (!this._supportPointerEvents) {\n this._deltaX = event.touches[0].clientX\n\n return\n }\n\n if (this._eventIsPointerPenTouch(event)) {\n this._deltaX = event.clientX\n }\n }\n\n _end(event) {\n if (this._eventIsPointerPenTouch(event)) {\n this._deltaX = event.clientX - this._deltaX\n }\n\n this._handleSwipe()\n execute(this._config.endCallback)\n }\n\n _move(event) {\n this._deltaX = event.touches && event.touches.length > 1 ?\n 0 :\n event.touches[0].clientX - this._deltaX\n }\n\n _handleSwipe() {\n const absDeltaX = Math.abs(this._deltaX)\n\n if (absDeltaX <= SWIPE_THRESHOLD) {\n return\n }\n\n const direction = absDeltaX / this._deltaX\n\n this._deltaX = 0\n\n if (!direction) {\n return\n }\n\n execute(direction > 0 ? this._config.rightCallback : this._config.leftCallback)\n }\n\n _initEvents() {\n if (this._supportPointerEvents) {\n EventHandler.on(this._element, EVENT_POINTERDOWN, event => this._start(event))\n EventHandler.on(this._element, EVENT_POINTERUP, event => this._end(event))\n\n this._element.classList.add(CLASS_NAME_POINTER_EVENT)\n } else {\n EventHandler.on(this._element, EVENT_TOUCHSTART, event => this._start(event))\n EventHandler.on(this._element, EVENT_TOUCHMOVE, event => this._move(event))\n EventHandler.on(this._element, EVENT_TOUCHEND, event => this._end(event))\n }\n }\n\n _eventIsPointerPenTouch(event) {\n return this._supportPointerEvents && (event.pointerType === POINTER_TYPE_PEN || event.pointerType === POINTER_TYPE_TOUCH)\n }\n\n // Static\n static isSupported() {\n return 'ontouchstart' in document.documentElement || navigator.maxTouchPoints > 0\n }\n}\n\nexport default Swipe\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap carousel.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport BaseComponent from './base-component.js'\nimport EventHandler from './dom/event-handler.js'\nimport Manipulator from './dom/manipulator.js'\nimport SelectorEngine from './dom/selector-engine.js'\nimport {\n defineJQueryPlugin,\n getNextActiveElement,\n isRTL,\n isVisible,\n reflow,\n triggerTransitionEnd\n} from './util/index.js'\nimport Swipe from './util/swipe.js'\n\n/**\n * Constants\n */\n\nconst NAME = 'carousel'\nconst DATA_KEY = 'bs.carousel'\nconst EVENT_KEY = `.${DATA_KEY}`\nconst DATA_API_KEY = '.data-api'\n\nconst ARROW_LEFT_KEY = 'ArrowLeft'\nconst ARROW_RIGHT_KEY = 'ArrowRight'\nconst TOUCHEVENT_COMPAT_WAIT = 500 // Time for mouse compat events to fire after touch\n\nconst ORDER_NEXT = 'next'\nconst ORDER_PREV = 'prev'\nconst DIRECTION_LEFT = 'left'\nconst DIRECTION_RIGHT = 'right'\n\nconst EVENT_SLIDE = `slide${EVENT_KEY}`\nconst EVENT_SLID = `slid${EVENT_KEY}`\nconst EVENT_KEYDOWN = `keydown${EVENT_KEY}`\nconst EVENT_MOUSEENTER = `mouseenter${EVENT_KEY}`\nconst EVENT_MOUSELEAVE = `mouseleave${EVENT_KEY}`\nconst EVENT_DRAG_START = `dragstart${EVENT_KEY}`\nconst EVENT_LOAD_DATA_API = `load${EVENT_KEY}${DATA_API_KEY}`\nconst EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`\n\nconst CLASS_NAME_CAROUSEL = 'carousel'\nconst CLASS_NAME_ACTIVE = 'active'\nconst CLASS_NAME_SLIDE = 'slide'\nconst CLASS_NAME_END = 'carousel-item-end'\nconst CLASS_NAME_START = 'carousel-item-start'\nconst CLASS_NAME_NEXT = 'carousel-item-next'\nconst CLASS_NAME_PREV = 'carousel-item-prev'\n\nconst SELECTOR_ACTIVE = '.active'\nconst SELECTOR_ITEM = '.carousel-item'\nconst SELECTOR_ACTIVE_ITEM = SELECTOR_ACTIVE + SELECTOR_ITEM\nconst SELECTOR_ITEM_IMG = '.carousel-item img'\nconst SELECTOR_INDICATORS = '.carousel-indicators'\nconst SELECTOR_DATA_SLIDE = '[data-bs-slide], [data-bs-slide-to]'\nconst SELECTOR_DATA_RIDE = '[data-bs-ride=\"carousel\"]'\n\nconst KEY_TO_DIRECTION = {\n [ARROW_LEFT_KEY]: DIRECTION_RIGHT,\n [ARROW_RIGHT_KEY]: DIRECTION_LEFT\n}\n\nconst Default = {\n interval: 5000,\n keyboard: true,\n pause: 'hover',\n ride: false,\n touch: true,\n wrap: true\n}\n\nconst DefaultType = {\n interval: '(number|boolean)', // TODO:v6 remove boolean support\n keyboard: 'boolean',\n pause: '(string|boolean)',\n ride: '(boolean|string)',\n touch: 'boolean',\n wrap: 'boolean'\n}\n\n/**\n * Class definition\n */\n\nclass Carousel extends BaseComponent {\n constructor(element, config) {\n super(element, config)\n\n this._interval = null\n this._activeElement = null\n this._isSliding = false\n this.touchTimeout = null\n this._swipeHelper = null\n\n this._indicatorsElement = SelectorEngine.findOne(SELECTOR_INDICATORS, this._element)\n this._addEventListeners()\n\n if (this._config.ride === CLASS_NAME_CAROUSEL) {\n this.cycle()\n }\n }\n\n // Getters\n static get Default() {\n return Default\n }\n\n static get DefaultType() {\n return DefaultType\n }\n\n static get NAME() {\n return NAME\n }\n\n // Public\n next() {\n this._slide(ORDER_NEXT)\n }\n\n nextWhenVisible() {\n // FIXME TODO use `document.visibilityState`\n // Don't call next when the page isn't visible\n // or the carousel or its parent isn't visible\n if (!document.hidden && isVisible(this._element)) {\n this.next()\n }\n }\n\n prev() {\n this._slide(ORDER_PREV)\n }\n\n pause() {\n if (this._isSliding) {\n triggerTransitionEnd(this._element)\n }\n\n this._clearInterval()\n }\n\n cycle() {\n this._clearInterval()\n this._updateInterval()\n\n this._interval = setInterval(() => this.nextWhenVisible(), this._config.interval)\n }\n\n _maybeEnableCycle() {\n if (!this._config.ride) {\n return\n }\n\n if (this._isSliding) {\n EventHandler.one(this._element, EVENT_SLID, () => this.cycle())\n return\n }\n\n this.cycle()\n }\n\n to(index) {\n const items = this._getItems()\n if (index > items.length - 1 || index < 0) {\n return\n }\n\n if (this._isSliding) {\n EventHandler.one(this._element, EVENT_SLID, () => this.to(index))\n return\n }\n\n const activeIndex = this._getItemIndex(this._getActive())\n if (activeIndex === index) {\n return\n }\n\n const order = index > activeIndex ? ORDER_NEXT : ORDER_PREV\n\n this._slide(order, items[index])\n }\n\n dispose() {\n if (this._swipeHelper) {\n this._swipeHelper.dispose()\n }\n\n super.dispose()\n }\n\n // Private\n _configAfterMerge(config) {\n config.defaultInterval = config.interval\n return config\n }\n\n _addEventListeners() {\n if (this._config.keyboard) {\n EventHandler.on(this._element, EVENT_KEYDOWN, event => this._keydown(event))\n }\n\n if (this._config.pause === 'hover') {\n EventHandler.on(this._element, EVENT_MOUSEENTER, () => this.pause())\n EventHandler.on(this._element, EVENT_MOUSELEAVE, () => this._maybeEnableCycle())\n }\n\n if (this._config.touch && Swipe.isSupported()) {\n this._addTouchEventListeners()\n }\n }\n\n _addTouchEventListeners() {\n for (const img of SelectorEngine.find(SELECTOR_ITEM_IMG, this._element)) {\n EventHandler.on(img, EVENT_DRAG_START, event => event.preventDefault())\n }\n\n const endCallBack = () => {\n if (this._config.pause !== 'hover') {\n return\n }\n\n // If it's a touch-enabled device, mouseenter/leave are fired as\n // part of the mouse compatibility events on first tap - the carousel\n // would stop cycling until user tapped out of it;\n // here, we listen for touchend, explicitly pause the carousel\n // (as if it's the second time we tap on it, mouseenter compat event\n // is NOT fired) and after a timeout (to allow for mouse compatibility\n // events to fire) we explicitly restart cycling\n\n this.pause()\n if (this.touchTimeout) {\n clearTimeout(this.touchTimeout)\n }\n\n this.touchTimeout = setTimeout(() => this._maybeEnableCycle(), TOUCHEVENT_COMPAT_WAIT + this._config.interval)\n }\n\n const swipeConfig = {\n leftCallback: () => this._slide(this._directionToOrder(DIRECTION_LEFT)),\n rightCallback: () => this._slide(this._directionToOrder(DIRECTION_RIGHT)),\n endCallback: endCallBack\n }\n\n this._swipeHelper = new Swipe(this._element, swipeConfig)\n }\n\n _keydown(event) {\n if (/input|textarea/i.test(event.target.tagName)) {\n return\n }\n\n const direction = KEY_TO_DIRECTION[event.key]\n if (direction) {\n event.preventDefault()\n this._slide(this._directionToOrder(direction))\n }\n }\n\n _getItemIndex(element) {\n return this._getItems().indexOf(element)\n }\n\n _setActiveIndicatorElement(index) {\n if (!this._indicatorsElement) {\n return\n }\n\n const activeIndicator = SelectorEngine.findOne(SELECTOR_ACTIVE, this._indicatorsElement)\n\n activeIndicator.classList.remove(CLASS_NAME_ACTIVE)\n activeIndicator.removeAttribute('aria-current')\n\n const newActiveIndicator = SelectorEngine.findOne(`[data-bs-slide-to=\"${index}\"]`, this._indicatorsElement)\n\n if (newActiveIndicator) {\n newActiveIndicator.classList.add(CLASS_NAME_ACTIVE)\n newActiveIndicator.setAttribute('aria-current', 'true')\n }\n }\n\n _updateInterval() {\n const element = this._activeElement || this._getActive()\n\n if (!element) {\n return\n }\n\n const elementInterval = Number.parseInt(element.getAttribute('data-bs-interval'), 10)\n\n this._config.interval = elementInterval || this._config.defaultInterval\n }\n\n _slide(order, element = null) {\n if (this._isSliding) {\n return\n }\n\n const activeElement = this._getActive()\n const isNext = order === ORDER_NEXT\n const nextElement = element || getNextActiveElement(this._getItems(), activeElement, isNext, this._config.wrap)\n\n if (nextElement === activeElement) {\n return\n }\n\n const nextElementIndex = this._getItemIndex(nextElement)\n\n const triggerEvent = eventName => {\n return EventHandler.trigger(this._element, eventName, {\n relatedTarget: nextElement,\n direction: this._orderToDirection(order),\n from: this._getItemIndex(activeElement),\n to: nextElementIndex\n })\n }\n\n const slideEvent = triggerEvent(EVENT_SLIDE)\n\n if (slideEvent.defaultPrevented) {\n return\n }\n\n if (!activeElement || !nextElement) {\n // Some weirdness is happening, so we bail\n // TODO: change tests that use empty divs to avoid this check\n return\n }\n\n const isCycling = Boolean(this._interval)\n this.pause()\n\n this._isSliding = true\n\n this._setActiveIndicatorElement(nextElementIndex)\n this._activeElement = nextElement\n\n const directionalClassName = isNext ? CLASS_NAME_START : CLASS_NAME_END\n const orderClassName = isNext ? CLASS_NAME_NEXT : CLASS_NAME_PREV\n\n nextElement.classList.add(orderClassName)\n\n reflow(nextElement)\n\n activeElement.classList.add(directionalClassName)\n nextElement.classList.add(directionalClassName)\n\n const completeCallBack = () => {\n nextElement.classList.remove(directionalClassName, orderClassName)\n nextElement.classList.add(CLASS_NAME_ACTIVE)\n\n activeElement.classList.remove(CLASS_NAME_ACTIVE, orderClassName, directionalClassName)\n\n this._isSliding = false\n\n triggerEvent(EVENT_SLID)\n }\n\n this._queueCallback(completeCallBack, activeElement, this._isAnimated())\n\n if (isCycling) {\n this.cycle()\n }\n }\n\n _isAnimated() {\n return this._element.classList.contains(CLASS_NAME_SLIDE)\n }\n\n _getActive() {\n return SelectorEngine.findOne(SELECTOR_ACTIVE_ITEM, this._element)\n }\n\n _getItems() {\n return SelectorEngine.find(SELECTOR_ITEM, this._element)\n }\n\n _clearInterval() {\n if (this._interval) {\n clearInterval(this._interval)\n this._interval = null\n }\n }\n\n _directionToOrder(direction) {\n if (isRTL()) {\n return direction === DIRECTION_LEFT ? ORDER_PREV : ORDER_NEXT\n }\n\n return direction === DIRECTION_LEFT ? ORDER_NEXT : ORDER_PREV\n }\n\n _orderToDirection(order) {\n if (isRTL()) {\n return order === ORDER_PREV ? DIRECTION_LEFT : DIRECTION_RIGHT\n }\n\n return order === ORDER_PREV ? DIRECTION_RIGHT : DIRECTION_LEFT\n }\n\n // Static\n static jQueryInterface(config) {\n return this.each(function () {\n const data = Carousel.getOrCreateInstance(this, config)\n\n if (typeof config === 'number') {\n data.to(config)\n return\n }\n\n if (typeof config === 'string') {\n if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {\n throw new TypeError(`No method named \"${config}\"`)\n }\n\n data[config]()\n }\n })\n }\n}\n\n/**\n * Data API implementation\n */\n\nEventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_SLIDE, function (event) {\n const target = SelectorEngine.getElementFromSelector(this)\n\n if (!target || !target.classList.contains(CLASS_NAME_CAROUSEL)) {\n return\n }\n\n event.preventDefault()\n\n const carousel = Carousel.getOrCreateInstance(target)\n const slideIndex = this.getAttribute('data-bs-slide-to')\n\n if (slideIndex) {\n carousel.to(slideIndex)\n carousel._maybeEnableCycle()\n return\n }\n\n if (Manipulator.getDataAttribute(this, 'slide') === 'next') {\n carousel.next()\n carousel._maybeEnableCycle()\n return\n }\n\n carousel.prev()\n carousel._maybeEnableCycle()\n})\n\nEventHandler.on(window, EVENT_LOAD_DATA_API, () => {\n const carousels = SelectorEngine.find(SELECTOR_DATA_RIDE)\n\n for (const carousel of carousels) {\n Carousel.getOrCreateInstance(carousel)\n }\n})\n\n/**\n * jQuery\n */\n\ndefineJQueryPlugin(Carousel)\n\nexport default Carousel\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap collapse.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport BaseComponent from './base-component.js'\nimport EventHandler from './dom/event-handler.js'\nimport SelectorEngine from './dom/selector-engine.js'\nimport {\n defineJQueryPlugin,\n getElement,\n reflow\n} from './util/index.js'\n\n/**\n * Constants\n */\n\nconst NAME = 'collapse'\nconst DATA_KEY = 'bs.collapse'\nconst EVENT_KEY = `.${DATA_KEY}`\nconst DATA_API_KEY = '.data-api'\n\nconst EVENT_SHOW = `show${EVENT_KEY}`\nconst EVENT_SHOWN = `shown${EVENT_KEY}`\nconst EVENT_HIDE = `hide${EVENT_KEY}`\nconst EVENT_HIDDEN = `hidden${EVENT_KEY}`\nconst EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`\n\nconst CLASS_NAME_SHOW = 'show'\nconst CLASS_NAME_COLLAPSE = 'collapse'\nconst CLASS_NAME_COLLAPSING = 'collapsing'\nconst CLASS_NAME_COLLAPSED = 'collapsed'\nconst CLASS_NAME_DEEPER_CHILDREN = `:scope .${CLASS_NAME_COLLAPSE} .${CLASS_NAME_COLLAPSE}`\nconst CLASS_NAME_HORIZONTAL = 'collapse-horizontal'\n\nconst WIDTH = 'width'\nconst HEIGHT = 'height'\n\nconst SELECTOR_ACTIVES = '.collapse.show, .collapse.collapsing'\nconst SELECTOR_DATA_TOGGLE = '[data-bs-toggle=\"collapse\"]'\n\nconst Default = {\n parent: null,\n toggle: true\n}\n\nconst DefaultType = {\n parent: '(null|element)',\n toggle: 'boolean'\n}\n\n/**\n * Class definition\n */\n\nclass Collapse extends BaseComponent {\n constructor(element, config) {\n super(element, config)\n\n this._isTransitioning = false\n this._triggerArray = []\n\n const toggleList = SelectorEngine.find(SELECTOR_DATA_TOGGLE)\n\n for (const elem of toggleList) {\n const selector = SelectorEngine.getSelectorFromElement(elem)\n const filterElement = SelectorEngine.find(selector)\n .filter(foundElement => foundElement === this._element)\n\n if (selector !== null && filterElement.length) {\n this._triggerArray.push(elem)\n }\n }\n\n this._initializeChildren()\n\n if (!this._config.parent) {\n this._addAriaAndCollapsedClass(this._triggerArray, this._isShown())\n }\n\n if (this._config.toggle) {\n this.toggle()\n }\n }\n\n // Getters\n static get Default() {\n return Default\n }\n\n static get DefaultType() {\n return DefaultType\n }\n\n static get NAME() {\n return NAME\n }\n\n // Public\n toggle() {\n if (this._isShown()) {\n this.hide()\n } else {\n this.show()\n }\n }\n\n show() {\n if (this._isTransitioning || this._isShown()) {\n return\n }\n\n let activeChildren = []\n\n // find active children\n if (this._config.parent) {\n activeChildren = this._getFirstLevelChildren(SELECTOR_ACTIVES)\n .filter(element => element !== this._element)\n .map(element => Collapse.getOrCreateInstance(element, { toggle: false }))\n }\n\n if (activeChildren.length && activeChildren[0]._isTransitioning) {\n return\n }\n\n const startEvent = EventHandler.trigger(this._element, EVENT_SHOW)\n if (startEvent.defaultPrevented) {\n return\n }\n\n for (const activeInstance of activeChildren) {\n activeInstance.hide()\n }\n\n const dimension = this._getDimension()\n\n this._element.classList.remove(CLASS_NAME_COLLAPSE)\n this._element.classList.add(CLASS_NAME_COLLAPSING)\n\n this._element.style[dimension] = 0\n\n this._addAriaAndCollapsedClass(this._triggerArray, true)\n this._isTransitioning = true\n\n const complete = () => {\n this._isTransitioning = false\n\n this._element.classList.remove(CLASS_NAME_COLLAPSING)\n this._element.classList.add(CLASS_NAME_COLLAPSE, CLASS_NAME_SHOW)\n\n this._element.style[dimension] = ''\n\n EventHandler.trigger(this._element, EVENT_SHOWN)\n }\n\n const capitalizedDimension = dimension[0].toUpperCase() + dimension.slice(1)\n const scrollSize = `scroll${capitalizedDimension}`\n\n this._queueCallback(complete, this._element, true)\n this._element.style[dimension] = `${this._element[scrollSize]}px`\n }\n\n hide() {\n if (this._isTransitioning || !this._isShown()) {\n return\n }\n\n const startEvent = EventHandler.trigger(this._element, EVENT_HIDE)\n if (startEvent.defaultPrevented) {\n return\n }\n\n const dimension = this._getDimension()\n\n this._element.style[dimension] = `${this._element.getBoundingClientRect()[dimension]}px`\n\n reflow(this._element)\n\n this._element.classList.add(CLASS_NAME_COLLAPSING)\n this._element.classList.remove(CLASS_NAME_COLLAPSE, CLASS_NAME_SHOW)\n\n for (const trigger of this._triggerArray) {\n const element = SelectorEngine.getElementFromSelector(trigger)\n\n if (element && !this._isShown(element)) {\n this._addAriaAndCollapsedClass([trigger], false)\n }\n }\n\n this._isTransitioning = true\n\n const complete = () => {\n this._isTransitioning = false\n this._element.classList.remove(CLASS_NAME_COLLAPSING)\n this._element.classList.add(CLASS_NAME_COLLAPSE)\n EventHandler.trigger(this._element, EVENT_HIDDEN)\n }\n\n this._element.style[dimension] = ''\n\n this._queueCallback(complete, this._element, true)\n }\n\n _isShown(element = this._element) {\n return element.classList.contains(CLASS_NAME_SHOW)\n }\n\n // Private\n _configAfterMerge(config) {\n config.toggle = Boolean(config.toggle) // Coerce string values\n config.parent = getElement(config.parent)\n return config\n }\n\n _getDimension() {\n return this._element.classList.contains(CLASS_NAME_HORIZONTAL) ? WIDTH : HEIGHT\n }\n\n _initializeChildren() {\n if (!this._config.parent) {\n return\n }\n\n const children = this._getFirstLevelChildren(SELECTOR_DATA_TOGGLE)\n\n for (const element of children) {\n const selected = SelectorEngine.getElementFromSelector(element)\n\n if (selected) {\n this._addAriaAndCollapsedClass([element], this._isShown(selected))\n }\n }\n }\n\n _getFirstLevelChildren(selector) {\n const children = SelectorEngine.find(CLASS_NAME_DEEPER_CHILDREN, this._config.parent)\n // remove children if greater depth\n return SelectorEngine.find(selector, this._config.parent).filter(element => !children.includes(element))\n }\n\n _addAriaAndCollapsedClass(triggerArray, isOpen) {\n if (!triggerArray.length) {\n return\n }\n\n for (const element of triggerArray) {\n element.classList.toggle(CLASS_NAME_COLLAPSED, !isOpen)\n element.setAttribute('aria-expanded', isOpen)\n }\n }\n\n // Static\n static jQueryInterface(config) {\n const _config = {}\n if (typeof config === 'string' && /show|hide/.test(config)) {\n _config.toggle = false\n }\n\n return this.each(function () {\n const data = Collapse.getOrCreateInstance(this, _config)\n\n if (typeof config === 'string') {\n if (typeof data[config] === 'undefined') {\n throw new TypeError(`No method named \"${config}\"`)\n }\n\n data[config]()\n }\n })\n }\n}\n\n/**\n * Data API implementation\n */\n\nEventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {\n // preventDefault only for elements (which change the URL) not inside the collapsible element\n if (event.target.tagName === 'A' || (event.delegateTarget && event.delegateTarget.tagName === 'A')) {\n event.preventDefault()\n }\n\n for (const element of SelectorEngine.getMultipleElementsFromSelector(this)) {\n Collapse.getOrCreateInstance(element, { toggle: false }).toggle()\n }\n})\n\n/**\n * jQuery\n */\n\ndefineJQueryPlugin(Collapse)\n\nexport default Collapse\n","export var top = 'top';\nexport var bottom = 'bottom';\nexport var right = 'right';\nexport var left = 'left';\nexport var auto = 'auto';\nexport var basePlacements = [top, bottom, right, left];\nexport var start = 'start';\nexport var end = 'end';\nexport var clippingParents = 'clippingParents';\nexport var viewport = 'viewport';\nexport var popper = 'popper';\nexport var reference = 'reference';\nexport var variationPlacements = /*#__PURE__*/basePlacements.reduce(function (acc, placement) {\n return acc.concat([placement + \"-\" + start, placement + \"-\" + end]);\n}, []);\nexport var placements = /*#__PURE__*/[].concat(basePlacements, [auto]).reduce(function (acc, placement) {\n return acc.concat([placement, placement + \"-\" + start, placement + \"-\" + end]);\n}, []); // modifiers that need to read the DOM\n\nexport var beforeRead = 'beforeRead';\nexport var read = 'read';\nexport var afterRead = 'afterRead'; // pure-logic modifiers\n\nexport var beforeMain = 'beforeMain';\nexport var main = 'main';\nexport var afterMain = 'afterMain'; // modifier with the purpose to write to the DOM (or write into a framework state)\n\nexport var beforeWrite = 'beforeWrite';\nexport var write = 'write';\nexport var afterWrite = 'afterWrite';\nexport var modifierPhases = [beforeRead, read, afterRead, beforeMain, main, afterMain, beforeWrite, write, afterWrite];","export default function getNodeName(element) {\n return element ? (element.nodeName || '').toLowerCase() : null;\n}","export default function getWindow(node) {\n if (node == null) {\n return window;\n }\n\n if (node.toString() !== '[object Window]') {\n var ownerDocument = node.ownerDocument;\n return ownerDocument ? ownerDocument.defaultView || window : window;\n }\n\n return node;\n}","import getWindow from \"./getWindow.js\";\n\nfunction isElement(node) {\n var OwnElement = getWindow(node).Element;\n return node instanceof OwnElement || node instanceof Element;\n}\n\nfunction isHTMLElement(node) {\n var OwnElement = getWindow(node).HTMLElement;\n return node instanceof OwnElement || node instanceof HTMLElement;\n}\n\nfunction isShadowRoot(node) {\n // IE 11 has no ShadowRoot\n if (typeof ShadowRoot === 'undefined') {\n return false;\n }\n\n var OwnElement = getWindow(node).ShadowRoot;\n return node instanceof OwnElement || node instanceof ShadowRoot;\n}\n\nexport { isElement, isHTMLElement, isShadowRoot };","import getNodeName from \"../dom-utils/getNodeName.js\";\nimport { isHTMLElement } from \"../dom-utils/instanceOf.js\"; // This modifier takes the styles prepared by the `computeStyles` modifier\n// and applies them to the HTMLElements such as popper and arrow\n\nfunction applyStyles(_ref) {\n var state = _ref.state;\n Object.keys(state.elements).forEach(function (name) {\n var style = state.styles[name] || {};\n var attributes = state.attributes[name] || {};\n var element = state.elements[name]; // arrow is optional + virtual elements\n\n if (!isHTMLElement(element) || !getNodeName(element)) {\n return;\n } // Flow doesn't support to extend this property, but it's the most\n // effective way to apply styles to an HTMLElement\n // $FlowFixMe[cannot-write]\n\n\n Object.assign(element.style, style);\n Object.keys(attributes).forEach(function (name) {\n var value = attributes[name];\n\n if (value === false) {\n element.removeAttribute(name);\n } else {\n element.setAttribute(name, value === true ? '' : value);\n }\n });\n });\n}\n\nfunction effect(_ref2) {\n var state = _ref2.state;\n var initialStyles = {\n popper: {\n position: state.options.strategy,\n left: '0',\n top: '0',\n margin: '0'\n },\n arrow: {\n position: 'absolute'\n },\n reference: {}\n };\n Object.assign(state.elements.popper.style, initialStyles.popper);\n state.styles = initialStyles;\n\n if (state.elements.arrow) {\n Object.assign(state.elements.arrow.style, initialStyles.arrow);\n }\n\n return function () {\n Object.keys(state.elements).forEach(function (name) {\n var element = state.elements[name];\n var attributes = state.attributes[name] || {};\n var styleProperties = Object.keys(state.styles.hasOwnProperty(name) ? state.styles[name] : initialStyles[name]); // Set all values to an empty string to unset them\n\n var style = styleProperties.reduce(function (style, property) {\n style[property] = '';\n return style;\n }, {}); // arrow is optional + virtual elements\n\n if (!isHTMLElement(element) || !getNodeName(element)) {\n return;\n }\n\n Object.assign(element.style, style);\n Object.keys(attributes).forEach(function (attribute) {\n element.removeAttribute(attribute);\n });\n });\n };\n} // eslint-disable-next-line import/no-unused-modules\n\n\nexport default {\n name: 'applyStyles',\n enabled: true,\n phase: 'write',\n fn: applyStyles,\n effect: effect,\n requires: ['computeStyles']\n};","import { auto } from \"../enums.js\";\nexport default function getBasePlacement(placement) {\n return placement.split('-')[0];\n}","export var max = Math.max;\nexport var min = Math.min;\nexport var round = Math.round;","export default function getUAString() {\n var uaData = navigator.userAgentData;\n\n if (uaData != null && uaData.brands && Array.isArray(uaData.brands)) {\n return uaData.brands.map(function (item) {\n return item.brand + \"/\" + item.version;\n }).join(' ');\n }\n\n return navigator.userAgent;\n}","import getUAString from \"../utils/userAgent.js\";\nexport default function isLayoutViewport() {\n return !/^((?!chrome|android).)*safari/i.test(getUAString());\n}","import { isElement, isHTMLElement } from \"./instanceOf.js\";\nimport { round } from \"../utils/math.js\";\nimport getWindow from \"./getWindow.js\";\nimport isLayoutViewport from \"./isLayoutViewport.js\";\nexport default function getBoundingClientRect(element, includeScale, isFixedStrategy) {\n if (includeScale === void 0) {\n includeScale = false;\n }\n\n if (isFixedStrategy === void 0) {\n isFixedStrategy = false;\n }\n\n var clientRect = element.getBoundingClientRect();\n var scaleX = 1;\n var scaleY = 1;\n\n if (includeScale && isHTMLElement(element)) {\n scaleX = element.offsetWidth > 0 ? round(clientRect.width) / element.offsetWidth || 1 : 1;\n scaleY = element.offsetHeight > 0 ? round(clientRect.height) / element.offsetHeight || 1 : 1;\n }\n\n var _ref = isElement(element) ? getWindow(element) : window,\n visualViewport = _ref.visualViewport;\n\n var addVisualOffsets = !isLayoutViewport() && isFixedStrategy;\n var x = (clientRect.left + (addVisualOffsets && visualViewport ? visualViewport.offsetLeft : 0)) / scaleX;\n var y = (clientRect.top + (addVisualOffsets && visualViewport ? visualViewport.offsetTop : 0)) / scaleY;\n var width = clientRect.width / scaleX;\n var height = clientRect.height / scaleY;\n return {\n width: width,\n height: height,\n top: y,\n right: x + width,\n bottom: y + height,\n left: x,\n x: x,\n y: y\n };\n}","import getBoundingClientRect from \"./getBoundingClientRect.js\"; // Returns the layout rect of an element relative to its offsetParent. Layout\n// means it doesn't take into account transforms.\n\nexport default function getLayoutRect(element) {\n var clientRect = getBoundingClientRect(element); // Use the clientRect sizes if it's not been transformed.\n // Fixes https://github.com/popperjs/popper-core/issues/1223\n\n var width = element.offsetWidth;\n var height = element.offsetHeight;\n\n if (Math.abs(clientRect.width - width) <= 1) {\n width = clientRect.width;\n }\n\n if (Math.abs(clientRect.height - height) <= 1) {\n height = clientRect.height;\n }\n\n return {\n x: element.offsetLeft,\n y: element.offsetTop,\n width: width,\n height: height\n };\n}","import { isShadowRoot } from \"./instanceOf.js\";\nexport default function contains(parent, child) {\n var rootNode = child.getRootNode && child.getRootNode(); // First, attempt with faster native method\n\n if (parent.contains(child)) {\n return true;\n } // then fallback to custom implementation with Shadow DOM support\n else if (rootNode && isShadowRoot(rootNode)) {\n var next = child;\n\n do {\n if (next && parent.isSameNode(next)) {\n return true;\n } // $FlowFixMe[prop-missing]: need a better way to handle this...\n\n\n next = next.parentNode || next.host;\n } while (next);\n } // Give up, the result is false\n\n\n return false;\n}","import getWindow from \"./getWindow.js\";\nexport default function getComputedStyle(element) {\n return getWindow(element).getComputedStyle(element);\n}","import getNodeName from \"./getNodeName.js\";\nexport default function isTableElement(element) {\n return ['table', 'td', 'th'].indexOf(getNodeName(element)) >= 0;\n}","import { isElement } from \"./instanceOf.js\";\nexport default function getDocumentElement(element) {\n // $FlowFixMe[incompatible-return]: assume body is always available\n return ((isElement(element) ? element.ownerDocument : // $FlowFixMe[prop-missing]\n element.document) || window.document).documentElement;\n}","import getNodeName from \"./getNodeName.js\";\nimport getDocumentElement from \"./getDocumentElement.js\";\nimport { isShadowRoot } from \"./instanceOf.js\";\nexport default function getParentNode(element) {\n if (getNodeName(element) === 'html') {\n return element;\n }\n\n return (// this is a quicker (but less type safe) way to save quite some bytes from the bundle\n // $FlowFixMe[incompatible-return]\n // $FlowFixMe[prop-missing]\n element.assignedSlot || // step into the shadow DOM of the parent of a slotted node\n element.parentNode || ( // DOM Element detected\n isShadowRoot(element) ? element.host : null) || // ShadowRoot detected\n // $FlowFixMe[incompatible-call]: HTMLElement is a Node\n getDocumentElement(element) // fallback\n\n );\n}","import getWindow from \"./getWindow.js\";\nimport getNodeName from \"./getNodeName.js\";\nimport getComputedStyle from \"./getComputedStyle.js\";\nimport { isHTMLElement, isShadowRoot } from \"./instanceOf.js\";\nimport isTableElement from \"./isTableElement.js\";\nimport getParentNode from \"./getParentNode.js\";\nimport getUAString from \"../utils/userAgent.js\";\n\nfunction getTrueOffsetParent(element) {\n if (!isHTMLElement(element) || // https://github.com/popperjs/popper-core/issues/837\n getComputedStyle(element).position === 'fixed') {\n return null;\n }\n\n return element.offsetParent;\n} // `.offsetParent` reports `null` for fixed elements, while absolute elements\n// return the containing block\n\n\nfunction getContainingBlock(element) {\n var isFirefox = /firefox/i.test(getUAString());\n var isIE = /Trident/i.test(getUAString());\n\n if (isIE && isHTMLElement(element)) {\n // In IE 9, 10 and 11 fixed elements containing block is always established by the viewport\n var elementCss = getComputedStyle(element);\n\n if (elementCss.position === 'fixed') {\n return null;\n }\n }\n\n var currentNode = getParentNode(element);\n\n if (isShadowRoot(currentNode)) {\n currentNode = currentNode.host;\n }\n\n while (isHTMLElement(currentNode) && ['html', 'body'].indexOf(getNodeName(currentNode)) < 0) {\n var css = getComputedStyle(currentNode); // This is non-exhaustive but covers the most common CSS properties that\n // create a containing block.\n // https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#identifying_the_containing_block\n\n if (css.transform !== 'none' || css.perspective !== 'none' || css.contain === 'paint' || ['transform', 'perspective'].indexOf(css.willChange) !== -1 || isFirefox && css.willChange === 'filter' || isFirefox && css.filter && css.filter !== 'none') {\n return currentNode;\n } else {\n currentNode = currentNode.parentNode;\n }\n }\n\n return null;\n} // Gets the closest ancestor positioned element. Handles some edge cases,\n// such as table ancestors and cross browser bugs.\n\n\nexport default function getOffsetParent(element) {\n var window = getWindow(element);\n var offsetParent = getTrueOffsetParent(element);\n\n while (offsetParent && isTableElement(offsetParent) && getComputedStyle(offsetParent).position === 'static') {\n offsetParent = getTrueOffsetParent(offsetParent);\n }\n\n if (offsetParent && (getNodeName(offsetParent) === 'html' || getNodeName(offsetParent) === 'body' && getComputedStyle(offsetParent).position === 'static')) {\n return window;\n }\n\n return offsetParent || getContainingBlock(element) || window;\n}","export default function getMainAxisFromPlacement(placement) {\n return ['top', 'bottom'].indexOf(placement) >= 0 ? 'x' : 'y';\n}","import { max as mathMax, min as mathMin } from \"./math.js\";\nexport function within(min, value, max) {\n return mathMax(min, mathMin(value, max));\n}\nexport function withinMaxClamp(min, value, max) {\n var v = within(min, value, max);\n return v > max ? max : v;\n}","import getFreshSideObject from \"./getFreshSideObject.js\";\nexport default function mergePaddingObject(paddingObject) {\n return Object.assign({}, getFreshSideObject(), paddingObject);\n}","export default function getFreshSideObject() {\n return {\n top: 0,\n right: 0,\n bottom: 0,\n left: 0\n };\n}","export default function expandToHashMap(value, keys) {\n return keys.reduce(function (hashMap, key) {\n hashMap[key] = value;\n return hashMap;\n }, {});\n}","import getBasePlacement from \"../utils/getBasePlacement.js\";\nimport getLayoutRect from \"../dom-utils/getLayoutRect.js\";\nimport contains from \"../dom-utils/contains.js\";\nimport getOffsetParent from \"../dom-utils/getOffsetParent.js\";\nimport getMainAxisFromPlacement from \"../utils/getMainAxisFromPlacement.js\";\nimport { within } from \"../utils/within.js\";\nimport mergePaddingObject from \"../utils/mergePaddingObject.js\";\nimport expandToHashMap from \"../utils/expandToHashMap.js\";\nimport { left, right, basePlacements, top, bottom } from \"../enums.js\"; // eslint-disable-next-line import/no-unused-modules\n\nvar toPaddingObject = function toPaddingObject(padding, state) {\n padding = typeof padding === 'function' ? padding(Object.assign({}, state.rects, {\n placement: state.placement\n })) : padding;\n return mergePaddingObject(typeof padding !== 'number' ? padding : expandToHashMap(padding, basePlacements));\n};\n\nfunction arrow(_ref) {\n var _state$modifiersData$;\n\n var state = _ref.state,\n name = _ref.name,\n options = _ref.options;\n var arrowElement = state.elements.arrow;\n var popperOffsets = state.modifiersData.popperOffsets;\n var basePlacement = getBasePlacement(state.placement);\n var axis = getMainAxisFromPlacement(basePlacement);\n var isVertical = [left, right].indexOf(basePlacement) >= 0;\n var len = isVertical ? 'height' : 'width';\n\n if (!arrowElement || !popperOffsets) {\n return;\n }\n\n var paddingObject = toPaddingObject(options.padding, state);\n var arrowRect = getLayoutRect(arrowElement);\n var minProp = axis === 'y' ? top : left;\n var maxProp = axis === 'y' ? bottom : right;\n var endDiff = state.rects.reference[len] + state.rects.reference[axis] - popperOffsets[axis] - state.rects.popper[len];\n var startDiff = popperOffsets[axis] - state.rects.reference[axis];\n var arrowOffsetParent = getOffsetParent(arrowElement);\n var clientSize = arrowOffsetParent ? axis === 'y' ? arrowOffsetParent.clientHeight || 0 : arrowOffsetParent.clientWidth || 0 : 0;\n var centerToReference = endDiff / 2 - startDiff / 2; // Make sure the arrow doesn't overflow the popper if the center point is\n // outside of the popper bounds\n\n var min = paddingObject[minProp];\n var max = clientSize - arrowRect[len] - paddingObject[maxProp];\n var center = clientSize / 2 - arrowRect[len] / 2 + centerToReference;\n var offset = within(min, center, max); // Prevents breaking syntax highlighting...\n\n var axisProp = axis;\n state.modifiersData[name] = (_state$modifiersData$ = {}, _state$modifiersData$[axisProp] = offset, _state$modifiersData$.centerOffset = offset - center, _state$modifiersData$);\n}\n\nfunction effect(_ref2) {\n var state = _ref2.state,\n options = _ref2.options;\n var _options$element = options.element,\n arrowElement = _options$element === void 0 ? '[data-popper-arrow]' : _options$element;\n\n if (arrowElement == null) {\n return;\n } // CSS selector\n\n\n if (typeof arrowElement === 'string') {\n arrowElement = state.elements.popper.querySelector(arrowElement);\n\n if (!arrowElement) {\n return;\n }\n }\n\n if (!contains(state.elements.popper, arrowElement)) {\n return;\n }\n\n state.elements.arrow = arrowElement;\n} // eslint-disable-next-line import/no-unused-modules\n\n\nexport default {\n name: 'arrow',\n enabled: true,\n phase: 'main',\n fn: arrow,\n effect: effect,\n requires: ['popperOffsets'],\n requiresIfExists: ['preventOverflow']\n};","export default function getVariation(placement) {\n return placement.split('-')[1];\n}","import { top, left, right, bottom, end } from \"../enums.js\";\nimport getOffsetParent from \"../dom-utils/getOffsetParent.js\";\nimport getWindow from \"../dom-utils/getWindow.js\";\nimport getDocumentElement from \"../dom-utils/getDocumentElement.js\";\nimport getComputedStyle from \"../dom-utils/getComputedStyle.js\";\nimport getBasePlacement from \"../utils/getBasePlacement.js\";\nimport getVariation from \"../utils/getVariation.js\";\nimport { round } from \"../utils/math.js\"; // eslint-disable-next-line import/no-unused-modules\n\nvar unsetSides = {\n top: 'auto',\n right: 'auto',\n bottom: 'auto',\n left: 'auto'\n}; // Round the offsets to the nearest suitable subpixel based on the DPR.\n// Zooming can change the DPR, but it seems to report a value that will\n// cleanly divide the values into the appropriate subpixels.\n\nfunction roundOffsetsByDPR(_ref, win) {\n var x = _ref.x,\n y = _ref.y;\n var dpr = win.devicePixelRatio || 1;\n return {\n x: round(x * dpr) / dpr || 0,\n y: round(y * dpr) / dpr || 0\n };\n}\n\nexport function mapToStyles(_ref2) {\n var _Object$assign2;\n\n var popper = _ref2.popper,\n popperRect = _ref2.popperRect,\n placement = _ref2.placement,\n variation = _ref2.variation,\n offsets = _ref2.offsets,\n position = _ref2.position,\n gpuAcceleration = _ref2.gpuAcceleration,\n adaptive = _ref2.adaptive,\n roundOffsets = _ref2.roundOffsets,\n isFixed = _ref2.isFixed;\n var _offsets$x = offsets.x,\n x = _offsets$x === void 0 ? 0 : _offsets$x,\n _offsets$y = offsets.y,\n y = _offsets$y === void 0 ? 0 : _offsets$y;\n\n var _ref3 = typeof roundOffsets === 'function' ? roundOffsets({\n x: x,\n y: y\n }) : {\n x: x,\n y: y\n };\n\n x = _ref3.x;\n y = _ref3.y;\n var hasX = offsets.hasOwnProperty('x');\n var hasY = offsets.hasOwnProperty('y');\n var sideX = left;\n var sideY = top;\n var win = window;\n\n if (adaptive) {\n var offsetParent = getOffsetParent(popper);\n var heightProp = 'clientHeight';\n var widthProp = 'clientWidth';\n\n if (offsetParent === getWindow(popper)) {\n offsetParent = getDocumentElement(popper);\n\n if (getComputedStyle(offsetParent).position !== 'static' && position === 'absolute') {\n heightProp = 'scrollHeight';\n widthProp = 'scrollWidth';\n }\n } // $FlowFixMe[incompatible-cast]: force type refinement, we compare offsetParent with window above, but Flow doesn't detect it\n\n\n offsetParent = offsetParent;\n\n if (placement === top || (placement === left || placement === right) && variation === end) {\n sideY = bottom;\n var offsetY = isFixed && offsetParent === win && win.visualViewport ? win.visualViewport.height : // $FlowFixMe[prop-missing]\n offsetParent[heightProp];\n y -= offsetY - popperRect.height;\n y *= gpuAcceleration ? 1 : -1;\n }\n\n if (placement === left || (placement === top || placement === bottom) && variation === end) {\n sideX = right;\n var offsetX = isFixed && offsetParent === win && win.visualViewport ? win.visualViewport.width : // $FlowFixMe[prop-missing]\n offsetParent[widthProp];\n x -= offsetX - popperRect.width;\n x *= gpuAcceleration ? 1 : -1;\n }\n }\n\n var commonStyles = Object.assign({\n position: position\n }, adaptive && unsetSides);\n\n var _ref4 = roundOffsets === true ? roundOffsetsByDPR({\n x: x,\n y: y\n }, getWindow(popper)) : {\n x: x,\n y: y\n };\n\n x = _ref4.x;\n y = _ref4.y;\n\n if (gpuAcceleration) {\n var _Object$assign;\n\n return Object.assign({}, commonStyles, (_Object$assign = {}, _Object$assign[sideY] = hasY ? '0' : '', _Object$assign[sideX] = hasX ? '0' : '', _Object$assign.transform = (win.devicePixelRatio || 1) <= 1 ? \"translate(\" + x + \"px, \" + y + \"px)\" : \"translate3d(\" + x + \"px, \" + y + \"px, 0)\", _Object$assign));\n }\n\n return Object.assign({}, commonStyles, (_Object$assign2 = {}, _Object$assign2[sideY] = hasY ? y + \"px\" : '', _Object$assign2[sideX] = hasX ? x + \"px\" : '', _Object$assign2.transform = '', _Object$assign2));\n}\n\nfunction computeStyles(_ref5) {\n var state = _ref5.state,\n options = _ref5.options;\n var _options$gpuAccelerat = options.gpuAcceleration,\n gpuAcceleration = _options$gpuAccelerat === void 0 ? true : _options$gpuAccelerat,\n _options$adaptive = options.adaptive,\n adaptive = _options$adaptive === void 0 ? true : _options$adaptive,\n _options$roundOffsets = options.roundOffsets,\n roundOffsets = _options$roundOffsets === void 0 ? true : _options$roundOffsets;\n var commonStyles = {\n placement: getBasePlacement(state.placement),\n variation: getVariation(state.placement),\n popper: state.elements.popper,\n popperRect: state.rects.popper,\n gpuAcceleration: gpuAcceleration,\n isFixed: state.options.strategy === 'fixed'\n };\n\n if (state.modifiersData.popperOffsets != null) {\n state.styles.popper = Object.assign({}, state.styles.popper, mapToStyles(Object.assign({}, commonStyles, {\n offsets: state.modifiersData.popperOffsets,\n position: state.options.strategy,\n adaptive: adaptive,\n roundOffsets: roundOffsets\n })));\n }\n\n if (state.modifiersData.arrow != null) {\n state.styles.arrow = Object.assign({}, state.styles.arrow, mapToStyles(Object.assign({}, commonStyles, {\n offsets: state.modifiersData.arrow,\n position: 'absolute',\n adaptive: false,\n roundOffsets: roundOffsets\n })));\n }\n\n state.attributes.popper = Object.assign({}, state.attributes.popper, {\n 'data-popper-placement': state.placement\n });\n} // eslint-disable-next-line import/no-unused-modules\n\n\nexport default {\n name: 'computeStyles',\n enabled: true,\n phase: 'beforeWrite',\n fn: computeStyles,\n data: {}\n};","import getWindow from \"../dom-utils/getWindow.js\"; // eslint-disable-next-line import/no-unused-modules\n\nvar passive = {\n passive: true\n};\n\nfunction effect(_ref) {\n var state = _ref.state,\n instance = _ref.instance,\n options = _ref.options;\n var _options$scroll = options.scroll,\n scroll = _options$scroll === void 0 ? true : _options$scroll,\n _options$resize = options.resize,\n resize = _options$resize === void 0 ? true : _options$resize;\n var window = getWindow(state.elements.popper);\n var scrollParents = [].concat(state.scrollParents.reference, state.scrollParents.popper);\n\n if (scroll) {\n scrollParents.forEach(function (scrollParent) {\n scrollParent.addEventListener('scroll', instance.update, passive);\n });\n }\n\n if (resize) {\n window.addEventListener('resize', instance.update, passive);\n }\n\n return function () {\n if (scroll) {\n scrollParents.forEach(function (scrollParent) {\n scrollParent.removeEventListener('scroll', instance.update, passive);\n });\n }\n\n if (resize) {\n window.removeEventListener('resize', instance.update, passive);\n }\n };\n} // eslint-disable-next-line import/no-unused-modules\n\n\nexport default {\n name: 'eventListeners',\n enabled: true,\n phase: 'write',\n fn: function fn() {},\n effect: effect,\n data: {}\n};","var hash = {\n left: 'right',\n right: 'left',\n bottom: 'top',\n top: 'bottom'\n};\nexport default function getOppositePlacement(placement) {\n return placement.replace(/left|right|bottom|top/g, function (matched) {\n return hash[matched];\n });\n}","var hash = {\n start: 'end',\n end: 'start'\n};\nexport default function getOppositeVariationPlacement(placement) {\n return placement.replace(/start|end/g, function (matched) {\n return hash[matched];\n });\n}","import getWindow from \"./getWindow.js\";\nexport default function getWindowScroll(node) {\n var win = getWindow(node);\n var scrollLeft = win.pageXOffset;\n var scrollTop = win.pageYOffset;\n return {\n scrollLeft: scrollLeft,\n scrollTop: scrollTop\n };\n}","import getBoundingClientRect from \"./getBoundingClientRect.js\";\nimport getDocumentElement from \"./getDocumentElement.js\";\nimport getWindowScroll from \"./getWindowScroll.js\";\nexport default function getWindowScrollBarX(element) {\n // If has a CSS width greater than the viewport, then this will be\n // incorrect for RTL.\n // Popper 1 is broken in this case and never had a bug report so let's assume\n // it's not an issue. I don't think anyone ever specifies width on \n // anyway.\n // Browsers where the left scrollbar doesn't cause an issue report `0` for\n // this (e.g. Edge 2019, IE11, Safari)\n return getBoundingClientRect(getDocumentElement(element)).left + getWindowScroll(element).scrollLeft;\n}","import getComputedStyle from \"./getComputedStyle.js\";\nexport default function isScrollParent(element) {\n // Firefox wants us to check `-x` and `-y` variations as well\n var _getComputedStyle = getComputedStyle(element),\n overflow = _getComputedStyle.overflow,\n overflowX = _getComputedStyle.overflowX,\n overflowY = _getComputedStyle.overflowY;\n\n return /auto|scroll|overlay|hidden/.test(overflow + overflowY + overflowX);\n}","import getParentNode from \"./getParentNode.js\";\nimport isScrollParent from \"./isScrollParent.js\";\nimport getNodeName from \"./getNodeName.js\";\nimport { isHTMLElement } from \"./instanceOf.js\";\nexport default function getScrollParent(node) {\n if (['html', 'body', '#document'].indexOf(getNodeName(node)) >= 0) {\n // $FlowFixMe[incompatible-return]: assume body is always available\n return node.ownerDocument.body;\n }\n\n if (isHTMLElement(node) && isScrollParent(node)) {\n return node;\n }\n\n return getScrollParent(getParentNode(node));\n}","import getScrollParent from \"./getScrollParent.js\";\nimport getParentNode from \"./getParentNode.js\";\nimport getWindow from \"./getWindow.js\";\nimport isScrollParent from \"./isScrollParent.js\";\n/*\ngiven a DOM element, return the list of all scroll parents, up the list of ancesors\nuntil we get to the top window object. This list is what we attach scroll listeners\nto, because if any of these parent elements scroll, we'll need to re-calculate the\nreference element's position.\n*/\n\nexport default function listScrollParents(element, list) {\n var _element$ownerDocumen;\n\n if (list === void 0) {\n list = [];\n }\n\n var scrollParent = getScrollParent(element);\n var isBody = scrollParent === ((_element$ownerDocumen = element.ownerDocument) == null ? void 0 : _element$ownerDocumen.body);\n var win = getWindow(scrollParent);\n var target = isBody ? [win].concat(win.visualViewport || [], isScrollParent(scrollParent) ? scrollParent : []) : scrollParent;\n var updatedList = list.concat(target);\n return isBody ? updatedList : // $FlowFixMe[incompatible-call]: isBody tells us target will be an HTMLElement here\n updatedList.concat(listScrollParents(getParentNode(target)));\n}","export default function rectToClientRect(rect) {\n return Object.assign({}, rect, {\n left: rect.x,\n top: rect.y,\n right: rect.x + rect.width,\n bottom: rect.y + rect.height\n });\n}","import { viewport } from \"../enums.js\";\nimport getViewportRect from \"./getViewportRect.js\";\nimport getDocumentRect from \"./getDocumentRect.js\";\nimport listScrollParents from \"./listScrollParents.js\";\nimport getOffsetParent from \"./getOffsetParent.js\";\nimport getDocumentElement from \"./getDocumentElement.js\";\nimport getComputedStyle from \"./getComputedStyle.js\";\nimport { isElement, isHTMLElement } from \"./instanceOf.js\";\nimport getBoundingClientRect from \"./getBoundingClientRect.js\";\nimport getParentNode from \"./getParentNode.js\";\nimport contains from \"./contains.js\";\nimport getNodeName from \"./getNodeName.js\";\nimport rectToClientRect from \"../utils/rectToClientRect.js\";\nimport { max, min } from \"../utils/math.js\";\n\nfunction getInnerBoundingClientRect(element, strategy) {\n var rect = getBoundingClientRect(element, false, strategy === 'fixed');\n rect.top = rect.top + element.clientTop;\n rect.left = rect.left + element.clientLeft;\n rect.bottom = rect.top + element.clientHeight;\n rect.right = rect.left + element.clientWidth;\n rect.width = element.clientWidth;\n rect.height = element.clientHeight;\n rect.x = rect.left;\n rect.y = rect.top;\n return rect;\n}\n\nfunction getClientRectFromMixedType(element, clippingParent, strategy) {\n return clippingParent === viewport ? rectToClientRect(getViewportRect(element, strategy)) : isElement(clippingParent) ? getInnerBoundingClientRect(clippingParent, strategy) : rectToClientRect(getDocumentRect(getDocumentElement(element)));\n} // A \"clipping parent\" is an overflowable container with the characteristic of\n// clipping (or hiding) overflowing elements with a position different from\n// `initial`\n\n\nfunction getClippingParents(element) {\n var clippingParents = listScrollParents(getParentNode(element));\n var canEscapeClipping = ['absolute', 'fixed'].indexOf(getComputedStyle(element).position) >= 0;\n var clipperElement = canEscapeClipping && isHTMLElement(element) ? getOffsetParent(element) : element;\n\n if (!isElement(clipperElement)) {\n return [];\n } // $FlowFixMe[incompatible-return]: https://github.com/facebook/flow/issues/1414\n\n\n return clippingParents.filter(function (clippingParent) {\n return isElement(clippingParent) && contains(clippingParent, clipperElement) && getNodeName(clippingParent) !== 'body';\n });\n} // Gets the maximum area that the element is visible in due to any number of\n// clipping parents\n\n\nexport default function getClippingRect(element, boundary, rootBoundary, strategy) {\n var mainClippingParents = boundary === 'clippingParents' ? getClippingParents(element) : [].concat(boundary);\n var clippingParents = [].concat(mainClippingParents, [rootBoundary]);\n var firstClippingParent = clippingParents[0];\n var clippingRect = clippingParents.reduce(function (accRect, clippingParent) {\n var rect = getClientRectFromMixedType(element, clippingParent, strategy);\n accRect.top = max(rect.top, accRect.top);\n accRect.right = min(rect.right, accRect.right);\n accRect.bottom = min(rect.bottom, accRect.bottom);\n accRect.left = max(rect.left, accRect.left);\n return accRect;\n }, getClientRectFromMixedType(element, firstClippingParent, strategy));\n clippingRect.width = clippingRect.right - clippingRect.left;\n clippingRect.height = clippingRect.bottom - clippingRect.top;\n clippingRect.x = clippingRect.left;\n clippingRect.y = clippingRect.top;\n return clippingRect;\n}","import getWindow from \"./getWindow.js\";\nimport getDocumentElement from \"./getDocumentElement.js\";\nimport getWindowScrollBarX from \"./getWindowScrollBarX.js\";\nimport isLayoutViewport from \"./isLayoutViewport.js\";\nexport default function getViewportRect(element, strategy) {\n var win = getWindow(element);\n var html = getDocumentElement(element);\n var visualViewport = win.visualViewport;\n var width = html.clientWidth;\n var height = html.clientHeight;\n var x = 0;\n var y = 0;\n\n if (visualViewport) {\n width = visualViewport.width;\n height = visualViewport.height;\n var layoutViewport = isLayoutViewport();\n\n if (layoutViewport || !layoutViewport && strategy === 'fixed') {\n x = visualViewport.offsetLeft;\n y = visualViewport.offsetTop;\n }\n }\n\n return {\n width: width,\n height: height,\n x: x + getWindowScrollBarX(element),\n y: y\n };\n}","import getDocumentElement from \"./getDocumentElement.js\";\nimport getComputedStyle from \"./getComputedStyle.js\";\nimport getWindowScrollBarX from \"./getWindowScrollBarX.js\";\nimport getWindowScroll from \"./getWindowScroll.js\";\nimport { max } from \"../utils/math.js\"; // Gets the entire size of the scrollable document area, even extending outside\n// of the `` and `` rect bounds if horizontally scrollable\n\nexport default function getDocumentRect(element) {\n var _element$ownerDocumen;\n\n var html = getDocumentElement(element);\n var winScroll = getWindowScroll(element);\n var body = (_element$ownerDocumen = element.ownerDocument) == null ? void 0 : _element$ownerDocumen.body;\n var width = max(html.scrollWidth, html.clientWidth, body ? body.scrollWidth : 0, body ? body.clientWidth : 0);\n var height = max(html.scrollHeight, html.clientHeight, body ? body.scrollHeight : 0, body ? body.clientHeight : 0);\n var x = -winScroll.scrollLeft + getWindowScrollBarX(element);\n var y = -winScroll.scrollTop;\n\n if (getComputedStyle(body || html).direction === 'rtl') {\n x += max(html.clientWidth, body ? body.clientWidth : 0) - width;\n }\n\n return {\n width: width,\n height: height,\n x: x,\n y: y\n };\n}","import getBasePlacement from \"./getBasePlacement.js\";\nimport getVariation from \"./getVariation.js\";\nimport getMainAxisFromPlacement from \"./getMainAxisFromPlacement.js\";\nimport { top, right, bottom, left, start, end } from \"../enums.js\";\nexport default function computeOffsets(_ref) {\n var reference = _ref.reference,\n element = _ref.element,\n placement = _ref.placement;\n var basePlacement = placement ? getBasePlacement(placement) : null;\n var variation = placement ? getVariation(placement) : null;\n var commonX = reference.x + reference.width / 2 - element.width / 2;\n var commonY = reference.y + reference.height / 2 - element.height / 2;\n var offsets;\n\n switch (basePlacement) {\n case top:\n offsets = {\n x: commonX,\n y: reference.y - element.height\n };\n break;\n\n case bottom:\n offsets = {\n x: commonX,\n y: reference.y + reference.height\n };\n break;\n\n case right:\n offsets = {\n x: reference.x + reference.width,\n y: commonY\n };\n break;\n\n case left:\n offsets = {\n x: reference.x - element.width,\n y: commonY\n };\n break;\n\n default:\n offsets = {\n x: reference.x,\n y: reference.y\n };\n }\n\n var mainAxis = basePlacement ? getMainAxisFromPlacement(basePlacement) : null;\n\n if (mainAxis != null) {\n var len = mainAxis === 'y' ? 'height' : 'width';\n\n switch (variation) {\n case start:\n offsets[mainAxis] = offsets[mainAxis] - (reference[len] / 2 - element[len] / 2);\n break;\n\n case end:\n offsets[mainAxis] = offsets[mainAxis] + (reference[len] / 2 - element[len] / 2);\n break;\n\n default:\n }\n }\n\n return offsets;\n}","import getClippingRect from \"../dom-utils/getClippingRect.js\";\nimport getDocumentElement from \"../dom-utils/getDocumentElement.js\";\nimport getBoundingClientRect from \"../dom-utils/getBoundingClientRect.js\";\nimport computeOffsets from \"./computeOffsets.js\";\nimport rectToClientRect from \"./rectToClientRect.js\";\nimport { clippingParents, reference, popper, bottom, top, right, basePlacements, viewport } from \"../enums.js\";\nimport { isElement } from \"../dom-utils/instanceOf.js\";\nimport mergePaddingObject from \"./mergePaddingObject.js\";\nimport expandToHashMap from \"./expandToHashMap.js\"; // eslint-disable-next-line import/no-unused-modules\n\nexport default function detectOverflow(state, options) {\n if (options === void 0) {\n options = {};\n }\n\n var _options = options,\n _options$placement = _options.placement,\n placement = _options$placement === void 0 ? state.placement : _options$placement,\n _options$strategy = _options.strategy,\n strategy = _options$strategy === void 0 ? state.strategy : _options$strategy,\n _options$boundary = _options.boundary,\n boundary = _options$boundary === void 0 ? clippingParents : _options$boundary,\n _options$rootBoundary = _options.rootBoundary,\n rootBoundary = _options$rootBoundary === void 0 ? viewport : _options$rootBoundary,\n _options$elementConte = _options.elementContext,\n elementContext = _options$elementConte === void 0 ? popper : _options$elementConte,\n _options$altBoundary = _options.altBoundary,\n altBoundary = _options$altBoundary === void 0 ? false : _options$altBoundary,\n _options$padding = _options.padding,\n padding = _options$padding === void 0 ? 0 : _options$padding;\n var paddingObject = mergePaddingObject(typeof padding !== 'number' ? padding : expandToHashMap(padding, basePlacements));\n var altContext = elementContext === popper ? reference : popper;\n var popperRect = state.rects.popper;\n var element = state.elements[altBoundary ? altContext : elementContext];\n var clippingClientRect = getClippingRect(isElement(element) ? element : element.contextElement || getDocumentElement(state.elements.popper), boundary, rootBoundary, strategy);\n var referenceClientRect = getBoundingClientRect(state.elements.reference);\n var popperOffsets = computeOffsets({\n reference: referenceClientRect,\n element: popperRect,\n strategy: 'absolute',\n placement: placement\n });\n var popperClientRect = rectToClientRect(Object.assign({}, popperRect, popperOffsets));\n var elementClientRect = elementContext === popper ? popperClientRect : referenceClientRect; // positive = overflowing the clipping rect\n // 0 or negative = within the clipping rect\n\n var overflowOffsets = {\n top: clippingClientRect.top - elementClientRect.top + paddingObject.top,\n bottom: elementClientRect.bottom - clippingClientRect.bottom + paddingObject.bottom,\n left: clippingClientRect.left - elementClientRect.left + paddingObject.left,\n right: elementClientRect.right - clippingClientRect.right + paddingObject.right\n };\n var offsetData = state.modifiersData.offset; // Offsets can be applied only to the popper element\n\n if (elementContext === popper && offsetData) {\n var offset = offsetData[placement];\n Object.keys(overflowOffsets).forEach(function (key) {\n var multiply = [right, bottom].indexOf(key) >= 0 ? 1 : -1;\n var axis = [top, bottom].indexOf(key) >= 0 ? 'y' : 'x';\n overflowOffsets[key] += offset[axis] * multiply;\n });\n }\n\n return overflowOffsets;\n}","import getVariation from \"./getVariation.js\";\nimport { variationPlacements, basePlacements, placements as allPlacements } from \"../enums.js\";\nimport detectOverflow from \"./detectOverflow.js\";\nimport getBasePlacement from \"./getBasePlacement.js\";\nexport default function computeAutoPlacement(state, options) {\n if (options === void 0) {\n options = {};\n }\n\n var _options = options,\n placement = _options.placement,\n boundary = _options.boundary,\n rootBoundary = _options.rootBoundary,\n padding = _options.padding,\n flipVariations = _options.flipVariations,\n _options$allowedAutoP = _options.allowedAutoPlacements,\n allowedAutoPlacements = _options$allowedAutoP === void 0 ? allPlacements : _options$allowedAutoP;\n var variation = getVariation(placement);\n var placements = variation ? flipVariations ? variationPlacements : variationPlacements.filter(function (placement) {\n return getVariation(placement) === variation;\n }) : basePlacements;\n var allowedPlacements = placements.filter(function (placement) {\n return allowedAutoPlacements.indexOf(placement) >= 0;\n });\n\n if (allowedPlacements.length === 0) {\n allowedPlacements = placements;\n } // $FlowFixMe[incompatible-type]: Flow seems to have problems with two array unions...\n\n\n var overflows = allowedPlacements.reduce(function (acc, placement) {\n acc[placement] = detectOverflow(state, {\n placement: placement,\n boundary: boundary,\n rootBoundary: rootBoundary,\n padding: padding\n })[getBasePlacement(placement)];\n return acc;\n }, {});\n return Object.keys(overflows).sort(function (a, b) {\n return overflows[a] - overflows[b];\n });\n}","import getOppositePlacement from \"../utils/getOppositePlacement.js\";\nimport getBasePlacement from \"../utils/getBasePlacement.js\";\nimport getOppositeVariationPlacement from \"../utils/getOppositeVariationPlacement.js\";\nimport detectOverflow from \"../utils/detectOverflow.js\";\nimport computeAutoPlacement from \"../utils/computeAutoPlacement.js\";\nimport { bottom, top, start, right, left, auto } from \"../enums.js\";\nimport getVariation from \"../utils/getVariation.js\"; // eslint-disable-next-line import/no-unused-modules\n\nfunction getExpandedFallbackPlacements(placement) {\n if (getBasePlacement(placement) === auto) {\n return [];\n }\n\n var oppositePlacement = getOppositePlacement(placement);\n return [getOppositeVariationPlacement(placement), oppositePlacement, getOppositeVariationPlacement(oppositePlacement)];\n}\n\nfunction flip(_ref) {\n var state = _ref.state,\n options = _ref.options,\n name = _ref.name;\n\n if (state.modifiersData[name]._skip) {\n return;\n }\n\n var _options$mainAxis = options.mainAxis,\n checkMainAxis = _options$mainAxis === void 0 ? true : _options$mainAxis,\n _options$altAxis = options.altAxis,\n checkAltAxis = _options$altAxis === void 0 ? true : _options$altAxis,\n specifiedFallbackPlacements = options.fallbackPlacements,\n padding = options.padding,\n boundary = options.boundary,\n rootBoundary = options.rootBoundary,\n altBoundary = options.altBoundary,\n _options$flipVariatio = options.flipVariations,\n flipVariations = _options$flipVariatio === void 0 ? true : _options$flipVariatio,\n allowedAutoPlacements = options.allowedAutoPlacements;\n var preferredPlacement = state.options.placement;\n var basePlacement = getBasePlacement(preferredPlacement);\n var isBasePlacement = basePlacement === preferredPlacement;\n var fallbackPlacements = specifiedFallbackPlacements || (isBasePlacement || !flipVariations ? [getOppositePlacement(preferredPlacement)] : getExpandedFallbackPlacements(preferredPlacement));\n var placements = [preferredPlacement].concat(fallbackPlacements).reduce(function (acc, placement) {\n return acc.concat(getBasePlacement(placement) === auto ? computeAutoPlacement(state, {\n placement: placement,\n boundary: boundary,\n rootBoundary: rootBoundary,\n padding: padding,\n flipVariations: flipVariations,\n allowedAutoPlacements: allowedAutoPlacements\n }) : placement);\n }, []);\n var referenceRect = state.rects.reference;\n var popperRect = state.rects.popper;\n var checksMap = new Map();\n var makeFallbackChecks = true;\n var firstFittingPlacement = placements[0];\n\n for (var i = 0; i < placements.length; i++) {\n var placement = placements[i];\n\n var _basePlacement = getBasePlacement(placement);\n\n var isStartVariation = getVariation(placement) === start;\n var isVertical = [top, bottom].indexOf(_basePlacement) >= 0;\n var len = isVertical ? 'width' : 'height';\n var overflow = detectOverflow(state, {\n placement: placement,\n boundary: boundary,\n rootBoundary: rootBoundary,\n altBoundary: altBoundary,\n padding: padding\n });\n var mainVariationSide = isVertical ? isStartVariation ? right : left : isStartVariation ? bottom : top;\n\n if (referenceRect[len] > popperRect[len]) {\n mainVariationSide = getOppositePlacement(mainVariationSide);\n }\n\n var altVariationSide = getOppositePlacement(mainVariationSide);\n var checks = [];\n\n if (checkMainAxis) {\n checks.push(overflow[_basePlacement] <= 0);\n }\n\n if (checkAltAxis) {\n checks.push(overflow[mainVariationSide] <= 0, overflow[altVariationSide] <= 0);\n }\n\n if (checks.every(function (check) {\n return check;\n })) {\n firstFittingPlacement = placement;\n makeFallbackChecks = false;\n break;\n }\n\n checksMap.set(placement, checks);\n }\n\n if (makeFallbackChecks) {\n // `2` may be desired in some cases – research later\n var numberOfChecks = flipVariations ? 3 : 1;\n\n var _loop = function _loop(_i) {\n var fittingPlacement = placements.find(function (placement) {\n var checks = checksMap.get(placement);\n\n if (checks) {\n return checks.slice(0, _i).every(function (check) {\n return check;\n });\n }\n });\n\n if (fittingPlacement) {\n firstFittingPlacement = fittingPlacement;\n return \"break\";\n }\n };\n\n for (var _i = numberOfChecks; _i > 0; _i--) {\n var _ret = _loop(_i);\n\n if (_ret === \"break\") break;\n }\n }\n\n if (state.placement !== firstFittingPlacement) {\n state.modifiersData[name]._skip = true;\n state.placement = firstFittingPlacement;\n state.reset = true;\n }\n} // eslint-disable-next-line import/no-unused-modules\n\n\nexport default {\n name: 'flip',\n enabled: true,\n phase: 'main',\n fn: flip,\n requiresIfExists: ['offset'],\n data: {\n _skip: false\n }\n};","import { top, bottom, left, right } from \"../enums.js\";\nimport detectOverflow from \"../utils/detectOverflow.js\";\n\nfunction getSideOffsets(overflow, rect, preventedOffsets) {\n if (preventedOffsets === void 0) {\n preventedOffsets = {\n x: 0,\n y: 0\n };\n }\n\n return {\n top: overflow.top - rect.height - preventedOffsets.y,\n right: overflow.right - rect.width + preventedOffsets.x,\n bottom: overflow.bottom - rect.height + preventedOffsets.y,\n left: overflow.left - rect.width - preventedOffsets.x\n };\n}\n\nfunction isAnySideFullyClipped(overflow) {\n return [top, right, bottom, left].some(function (side) {\n return overflow[side] >= 0;\n });\n}\n\nfunction hide(_ref) {\n var state = _ref.state,\n name = _ref.name;\n var referenceRect = state.rects.reference;\n var popperRect = state.rects.popper;\n var preventedOffsets = state.modifiersData.preventOverflow;\n var referenceOverflow = detectOverflow(state, {\n elementContext: 'reference'\n });\n var popperAltOverflow = detectOverflow(state, {\n altBoundary: true\n });\n var referenceClippingOffsets = getSideOffsets(referenceOverflow, referenceRect);\n var popperEscapeOffsets = getSideOffsets(popperAltOverflow, popperRect, preventedOffsets);\n var isReferenceHidden = isAnySideFullyClipped(referenceClippingOffsets);\n var hasPopperEscaped = isAnySideFullyClipped(popperEscapeOffsets);\n state.modifiersData[name] = {\n referenceClippingOffsets: referenceClippingOffsets,\n popperEscapeOffsets: popperEscapeOffsets,\n isReferenceHidden: isReferenceHidden,\n hasPopperEscaped: hasPopperEscaped\n };\n state.attributes.popper = Object.assign({}, state.attributes.popper, {\n 'data-popper-reference-hidden': isReferenceHidden,\n 'data-popper-escaped': hasPopperEscaped\n });\n} // eslint-disable-next-line import/no-unused-modules\n\n\nexport default {\n name: 'hide',\n enabled: true,\n phase: 'main',\n requiresIfExists: ['preventOverflow'],\n fn: hide\n};","import getBasePlacement from \"../utils/getBasePlacement.js\";\nimport { top, left, right, placements } from \"../enums.js\"; // eslint-disable-next-line import/no-unused-modules\n\nexport function distanceAndSkiddingToXY(placement, rects, offset) {\n var basePlacement = getBasePlacement(placement);\n var invertDistance = [left, top].indexOf(basePlacement) >= 0 ? -1 : 1;\n\n var _ref = typeof offset === 'function' ? offset(Object.assign({}, rects, {\n placement: placement\n })) : offset,\n skidding = _ref[0],\n distance = _ref[1];\n\n skidding = skidding || 0;\n distance = (distance || 0) * invertDistance;\n return [left, right].indexOf(basePlacement) >= 0 ? {\n x: distance,\n y: skidding\n } : {\n x: skidding,\n y: distance\n };\n}\n\nfunction offset(_ref2) {\n var state = _ref2.state,\n options = _ref2.options,\n name = _ref2.name;\n var _options$offset = options.offset,\n offset = _options$offset === void 0 ? [0, 0] : _options$offset;\n var data = placements.reduce(function (acc, placement) {\n acc[placement] = distanceAndSkiddingToXY(placement, state.rects, offset);\n return acc;\n }, {});\n var _data$state$placement = data[state.placement],\n x = _data$state$placement.x,\n y = _data$state$placement.y;\n\n if (state.modifiersData.popperOffsets != null) {\n state.modifiersData.popperOffsets.x += x;\n state.modifiersData.popperOffsets.y += y;\n }\n\n state.modifiersData[name] = data;\n} // eslint-disable-next-line import/no-unused-modules\n\n\nexport default {\n name: 'offset',\n enabled: true,\n phase: 'main',\n requires: ['popperOffsets'],\n fn: offset\n};","import computeOffsets from \"../utils/computeOffsets.js\";\n\nfunction popperOffsets(_ref) {\n var state = _ref.state,\n name = _ref.name;\n // Offsets are the actual position the popper needs to have to be\n // properly positioned near its reference element\n // This is the most basic placement, and will be adjusted by\n // the modifiers in the next step\n state.modifiersData[name] = computeOffsets({\n reference: state.rects.reference,\n element: state.rects.popper,\n strategy: 'absolute',\n placement: state.placement\n });\n} // eslint-disable-next-line import/no-unused-modules\n\n\nexport default {\n name: 'popperOffsets',\n enabled: true,\n phase: 'read',\n fn: popperOffsets,\n data: {}\n};","import { top, left, right, bottom, start } from \"../enums.js\";\nimport getBasePlacement from \"../utils/getBasePlacement.js\";\nimport getMainAxisFromPlacement from \"../utils/getMainAxisFromPlacement.js\";\nimport getAltAxis from \"../utils/getAltAxis.js\";\nimport { within, withinMaxClamp } from \"../utils/within.js\";\nimport getLayoutRect from \"../dom-utils/getLayoutRect.js\";\nimport getOffsetParent from \"../dom-utils/getOffsetParent.js\";\nimport detectOverflow from \"../utils/detectOverflow.js\";\nimport getVariation from \"../utils/getVariation.js\";\nimport getFreshSideObject from \"../utils/getFreshSideObject.js\";\nimport { min as mathMin, max as mathMax } from \"../utils/math.js\";\n\nfunction preventOverflow(_ref) {\n var state = _ref.state,\n options = _ref.options,\n name = _ref.name;\n var _options$mainAxis = options.mainAxis,\n checkMainAxis = _options$mainAxis === void 0 ? true : _options$mainAxis,\n _options$altAxis = options.altAxis,\n checkAltAxis = _options$altAxis === void 0 ? false : _options$altAxis,\n boundary = options.boundary,\n rootBoundary = options.rootBoundary,\n altBoundary = options.altBoundary,\n padding = options.padding,\n _options$tether = options.tether,\n tether = _options$tether === void 0 ? true : _options$tether,\n _options$tetherOffset = options.tetherOffset,\n tetherOffset = _options$tetherOffset === void 0 ? 0 : _options$tetherOffset;\n var overflow = detectOverflow(state, {\n boundary: boundary,\n rootBoundary: rootBoundary,\n padding: padding,\n altBoundary: altBoundary\n });\n var basePlacement = getBasePlacement(state.placement);\n var variation = getVariation(state.placement);\n var isBasePlacement = !variation;\n var mainAxis = getMainAxisFromPlacement(basePlacement);\n var altAxis = getAltAxis(mainAxis);\n var popperOffsets = state.modifiersData.popperOffsets;\n var referenceRect = state.rects.reference;\n var popperRect = state.rects.popper;\n var tetherOffsetValue = typeof tetherOffset === 'function' ? tetherOffset(Object.assign({}, state.rects, {\n placement: state.placement\n })) : tetherOffset;\n var normalizedTetherOffsetValue = typeof tetherOffsetValue === 'number' ? {\n mainAxis: tetherOffsetValue,\n altAxis: tetherOffsetValue\n } : Object.assign({\n mainAxis: 0,\n altAxis: 0\n }, tetherOffsetValue);\n var offsetModifierState = state.modifiersData.offset ? state.modifiersData.offset[state.placement] : null;\n var data = {\n x: 0,\n y: 0\n };\n\n if (!popperOffsets) {\n return;\n }\n\n if (checkMainAxis) {\n var _offsetModifierState$;\n\n var mainSide = mainAxis === 'y' ? top : left;\n var altSide = mainAxis === 'y' ? bottom : right;\n var len = mainAxis === 'y' ? 'height' : 'width';\n var offset = popperOffsets[mainAxis];\n var min = offset + overflow[mainSide];\n var max = offset - overflow[altSide];\n var additive = tether ? -popperRect[len] / 2 : 0;\n var minLen = variation === start ? referenceRect[len] : popperRect[len];\n var maxLen = variation === start ? -popperRect[len] : -referenceRect[len]; // We need to include the arrow in the calculation so the arrow doesn't go\n // outside the reference bounds\n\n var arrowElement = state.elements.arrow;\n var arrowRect = tether && arrowElement ? getLayoutRect(arrowElement) : {\n width: 0,\n height: 0\n };\n var arrowPaddingObject = state.modifiersData['arrow#persistent'] ? state.modifiersData['arrow#persistent'].padding : getFreshSideObject();\n var arrowPaddingMin = arrowPaddingObject[mainSide];\n var arrowPaddingMax = arrowPaddingObject[altSide]; // If the reference length is smaller than the arrow length, we don't want\n // to include its full size in the calculation. If the reference is small\n // and near the edge of a boundary, the popper can overflow even if the\n // reference is not overflowing as well (e.g. virtual elements with no\n // width or height)\n\n var arrowLen = within(0, referenceRect[len], arrowRect[len]);\n var minOffset = isBasePlacement ? referenceRect[len] / 2 - additive - arrowLen - arrowPaddingMin - normalizedTetherOffsetValue.mainAxis : minLen - arrowLen - arrowPaddingMin - normalizedTetherOffsetValue.mainAxis;\n var maxOffset = isBasePlacement ? -referenceRect[len] / 2 + additive + arrowLen + arrowPaddingMax + normalizedTetherOffsetValue.mainAxis : maxLen + arrowLen + arrowPaddingMax + normalizedTetherOffsetValue.mainAxis;\n var arrowOffsetParent = state.elements.arrow && getOffsetParent(state.elements.arrow);\n var clientOffset = arrowOffsetParent ? mainAxis === 'y' ? arrowOffsetParent.clientTop || 0 : arrowOffsetParent.clientLeft || 0 : 0;\n var offsetModifierValue = (_offsetModifierState$ = offsetModifierState == null ? void 0 : offsetModifierState[mainAxis]) != null ? _offsetModifierState$ : 0;\n var tetherMin = offset + minOffset - offsetModifierValue - clientOffset;\n var tetherMax = offset + maxOffset - offsetModifierValue;\n var preventedOffset = within(tether ? mathMin(min, tetherMin) : min, offset, tether ? mathMax(max, tetherMax) : max);\n popperOffsets[mainAxis] = preventedOffset;\n data[mainAxis] = preventedOffset - offset;\n }\n\n if (checkAltAxis) {\n var _offsetModifierState$2;\n\n var _mainSide = mainAxis === 'x' ? top : left;\n\n var _altSide = mainAxis === 'x' ? bottom : right;\n\n var _offset = popperOffsets[altAxis];\n\n var _len = altAxis === 'y' ? 'height' : 'width';\n\n var _min = _offset + overflow[_mainSide];\n\n var _max = _offset - overflow[_altSide];\n\n var isOriginSide = [top, left].indexOf(basePlacement) !== -1;\n\n var _offsetModifierValue = (_offsetModifierState$2 = offsetModifierState == null ? void 0 : offsetModifierState[altAxis]) != null ? _offsetModifierState$2 : 0;\n\n var _tetherMin = isOriginSide ? _min : _offset - referenceRect[_len] - popperRect[_len] - _offsetModifierValue + normalizedTetherOffsetValue.altAxis;\n\n var _tetherMax = isOriginSide ? _offset + referenceRect[_len] + popperRect[_len] - _offsetModifierValue - normalizedTetherOffsetValue.altAxis : _max;\n\n var _preventedOffset = tether && isOriginSide ? withinMaxClamp(_tetherMin, _offset, _tetherMax) : within(tether ? _tetherMin : _min, _offset, tether ? _tetherMax : _max);\n\n popperOffsets[altAxis] = _preventedOffset;\n data[altAxis] = _preventedOffset - _offset;\n }\n\n state.modifiersData[name] = data;\n} // eslint-disable-next-line import/no-unused-modules\n\n\nexport default {\n name: 'preventOverflow',\n enabled: true,\n phase: 'main',\n fn: preventOverflow,\n requiresIfExists: ['offset']\n};","export default function getAltAxis(axis) {\n return axis === 'x' ? 'y' : 'x';\n}","import getBoundingClientRect from \"./getBoundingClientRect.js\";\nimport getNodeScroll from \"./getNodeScroll.js\";\nimport getNodeName from \"./getNodeName.js\";\nimport { isHTMLElement } from \"./instanceOf.js\";\nimport getWindowScrollBarX from \"./getWindowScrollBarX.js\";\nimport getDocumentElement from \"./getDocumentElement.js\";\nimport isScrollParent from \"./isScrollParent.js\";\nimport { round } from \"../utils/math.js\";\n\nfunction isElementScaled(element) {\n var rect = element.getBoundingClientRect();\n var scaleX = round(rect.width) / element.offsetWidth || 1;\n var scaleY = round(rect.height) / element.offsetHeight || 1;\n return scaleX !== 1 || scaleY !== 1;\n} // Returns the composite rect of an element relative to its offsetParent.\n// Composite means it takes into account transforms as well as layout.\n\n\nexport default function getCompositeRect(elementOrVirtualElement, offsetParent, isFixed) {\n if (isFixed === void 0) {\n isFixed = false;\n }\n\n var isOffsetParentAnElement = isHTMLElement(offsetParent);\n var offsetParentIsScaled = isHTMLElement(offsetParent) && isElementScaled(offsetParent);\n var documentElement = getDocumentElement(offsetParent);\n var rect = getBoundingClientRect(elementOrVirtualElement, offsetParentIsScaled, isFixed);\n var scroll = {\n scrollLeft: 0,\n scrollTop: 0\n };\n var offsets = {\n x: 0,\n y: 0\n };\n\n if (isOffsetParentAnElement || !isOffsetParentAnElement && !isFixed) {\n if (getNodeName(offsetParent) !== 'body' || // https://github.com/popperjs/popper-core/issues/1078\n isScrollParent(documentElement)) {\n scroll = getNodeScroll(offsetParent);\n }\n\n if (isHTMLElement(offsetParent)) {\n offsets = getBoundingClientRect(offsetParent, true);\n offsets.x += offsetParent.clientLeft;\n offsets.y += offsetParent.clientTop;\n } else if (documentElement) {\n offsets.x = getWindowScrollBarX(documentElement);\n }\n }\n\n return {\n x: rect.left + scroll.scrollLeft - offsets.x,\n y: rect.top + scroll.scrollTop - offsets.y,\n width: rect.width,\n height: rect.height\n };\n}","import getWindowScroll from \"./getWindowScroll.js\";\nimport getWindow from \"./getWindow.js\";\nimport { isHTMLElement } from \"./instanceOf.js\";\nimport getHTMLElementScroll from \"./getHTMLElementScroll.js\";\nexport default function getNodeScroll(node) {\n if (node === getWindow(node) || !isHTMLElement(node)) {\n return getWindowScroll(node);\n } else {\n return getHTMLElementScroll(node);\n }\n}","export default function getHTMLElementScroll(element) {\n return {\n scrollLeft: element.scrollLeft,\n scrollTop: element.scrollTop\n };\n}","import { modifierPhases } from \"../enums.js\"; // source: https://stackoverflow.com/questions/49875255\n\nfunction order(modifiers) {\n var map = new Map();\n var visited = new Set();\n var result = [];\n modifiers.forEach(function (modifier) {\n map.set(modifier.name, modifier);\n }); // On visiting object, check for its dependencies and visit them recursively\n\n function sort(modifier) {\n visited.add(modifier.name);\n var requires = [].concat(modifier.requires || [], modifier.requiresIfExists || []);\n requires.forEach(function (dep) {\n if (!visited.has(dep)) {\n var depModifier = map.get(dep);\n\n if (depModifier) {\n sort(depModifier);\n }\n }\n });\n result.push(modifier);\n }\n\n modifiers.forEach(function (modifier) {\n if (!visited.has(modifier.name)) {\n // check for visited object\n sort(modifier);\n }\n });\n return result;\n}\n\nexport default function orderModifiers(modifiers) {\n // order based on dependencies\n var orderedModifiers = order(modifiers); // order based on phase\n\n return modifierPhases.reduce(function (acc, phase) {\n return acc.concat(orderedModifiers.filter(function (modifier) {\n return modifier.phase === phase;\n }));\n }, []);\n}","import getCompositeRect from \"./dom-utils/getCompositeRect.js\";\nimport getLayoutRect from \"./dom-utils/getLayoutRect.js\";\nimport listScrollParents from \"./dom-utils/listScrollParents.js\";\nimport getOffsetParent from \"./dom-utils/getOffsetParent.js\";\nimport orderModifiers from \"./utils/orderModifiers.js\";\nimport debounce from \"./utils/debounce.js\";\nimport mergeByName from \"./utils/mergeByName.js\";\nimport detectOverflow from \"./utils/detectOverflow.js\";\nimport { isElement } from \"./dom-utils/instanceOf.js\";\nvar DEFAULT_OPTIONS = {\n placement: 'bottom',\n modifiers: [],\n strategy: 'absolute'\n};\n\nfunction areValidElements() {\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n return !args.some(function (element) {\n return !(element && typeof element.getBoundingClientRect === 'function');\n });\n}\n\nexport function popperGenerator(generatorOptions) {\n if (generatorOptions === void 0) {\n generatorOptions = {};\n }\n\n var _generatorOptions = generatorOptions,\n _generatorOptions$def = _generatorOptions.defaultModifiers,\n defaultModifiers = _generatorOptions$def === void 0 ? [] : _generatorOptions$def,\n _generatorOptions$def2 = _generatorOptions.defaultOptions,\n defaultOptions = _generatorOptions$def2 === void 0 ? DEFAULT_OPTIONS : _generatorOptions$def2;\n return function createPopper(reference, popper, options) {\n if (options === void 0) {\n options = defaultOptions;\n }\n\n var state = {\n placement: 'bottom',\n orderedModifiers: [],\n options: Object.assign({}, DEFAULT_OPTIONS, defaultOptions),\n modifiersData: {},\n elements: {\n reference: reference,\n popper: popper\n },\n attributes: {},\n styles: {}\n };\n var effectCleanupFns = [];\n var isDestroyed = false;\n var instance = {\n state: state,\n setOptions: function setOptions(setOptionsAction) {\n var options = typeof setOptionsAction === 'function' ? setOptionsAction(state.options) : setOptionsAction;\n cleanupModifierEffects();\n state.options = Object.assign({}, defaultOptions, state.options, options);\n state.scrollParents = {\n reference: isElement(reference) ? listScrollParents(reference) : reference.contextElement ? listScrollParents(reference.contextElement) : [],\n popper: listScrollParents(popper)\n }; // Orders the modifiers based on their dependencies and `phase`\n // properties\n\n var orderedModifiers = orderModifiers(mergeByName([].concat(defaultModifiers, state.options.modifiers))); // Strip out disabled modifiers\n\n state.orderedModifiers = orderedModifiers.filter(function (m) {\n return m.enabled;\n });\n runModifierEffects();\n return instance.update();\n },\n // Sync update – it will always be executed, even if not necessary. This\n // is useful for low frequency updates where sync behavior simplifies the\n // logic.\n // For high frequency updates (e.g. `resize` and `scroll` events), always\n // prefer the async Popper#update method\n forceUpdate: function forceUpdate() {\n if (isDestroyed) {\n return;\n }\n\n var _state$elements = state.elements,\n reference = _state$elements.reference,\n popper = _state$elements.popper; // Don't proceed if `reference` or `popper` are not valid elements\n // anymore\n\n if (!areValidElements(reference, popper)) {\n return;\n } // Store the reference and popper rects to be read by modifiers\n\n\n state.rects = {\n reference: getCompositeRect(reference, getOffsetParent(popper), state.options.strategy === 'fixed'),\n popper: getLayoutRect(popper)\n }; // Modifiers have the ability to reset the current update cycle. The\n // most common use case for this is the `flip` modifier changing the\n // placement, which then needs to re-run all the modifiers, because the\n // logic was previously ran for the previous placement and is therefore\n // stale/incorrect\n\n state.reset = false;\n state.placement = state.options.placement; // On each update cycle, the `modifiersData` property for each modifier\n // is filled with the initial data specified by the modifier. This means\n // it doesn't persist and is fresh on each update.\n // To ensure persistent data, use `${name}#persistent`\n\n state.orderedModifiers.forEach(function (modifier) {\n return state.modifiersData[modifier.name] = Object.assign({}, modifier.data);\n });\n\n for (var index = 0; index < state.orderedModifiers.length; index++) {\n if (state.reset === true) {\n state.reset = false;\n index = -1;\n continue;\n }\n\n var _state$orderedModifie = state.orderedModifiers[index],\n fn = _state$orderedModifie.fn,\n _state$orderedModifie2 = _state$orderedModifie.options,\n _options = _state$orderedModifie2 === void 0 ? {} : _state$orderedModifie2,\n name = _state$orderedModifie.name;\n\n if (typeof fn === 'function') {\n state = fn({\n state: state,\n options: _options,\n name: name,\n instance: instance\n }) || state;\n }\n }\n },\n // Async and optimistically optimized update – it will not be executed if\n // not necessary (debounced to run at most once-per-tick)\n update: debounce(function () {\n return new Promise(function (resolve) {\n instance.forceUpdate();\n resolve(state);\n });\n }),\n destroy: function destroy() {\n cleanupModifierEffects();\n isDestroyed = true;\n }\n };\n\n if (!areValidElements(reference, popper)) {\n return instance;\n }\n\n instance.setOptions(options).then(function (state) {\n if (!isDestroyed && options.onFirstUpdate) {\n options.onFirstUpdate(state);\n }\n }); // Modifiers have the ability to execute arbitrary code before the first\n // update cycle runs. They will be executed in the same order as the update\n // cycle. This is useful when a modifier adds some persistent data that\n // other modifiers need to use, but the modifier is run after the dependent\n // one.\n\n function runModifierEffects() {\n state.orderedModifiers.forEach(function (_ref) {\n var name = _ref.name,\n _ref$options = _ref.options,\n options = _ref$options === void 0 ? {} : _ref$options,\n effect = _ref.effect;\n\n if (typeof effect === 'function') {\n var cleanupFn = effect({\n state: state,\n name: name,\n instance: instance,\n options: options\n });\n\n var noopFn = function noopFn() {};\n\n effectCleanupFns.push(cleanupFn || noopFn);\n }\n });\n }\n\n function cleanupModifierEffects() {\n effectCleanupFns.forEach(function (fn) {\n return fn();\n });\n effectCleanupFns = [];\n }\n\n return instance;\n };\n}\nexport var createPopper = /*#__PURE__*/popperGenerator(); // eslint-disable-next-line import/no-unused-modules\n\nexport { detectOverflow };","export default function debounce(fn) {\n var pending;\n return function () {\n if (!pending) {\n pending = new Promise(function (resolve) {\n Promise.resolve().then(function () {\n pending = undefined;\n resolve(fn());\n });\n });\n }\n\n return pending;\n };\n}","export default function mergeByName(modifiers) {\n var merged = modifiers.reduce(function (merged, current) {\n var existing = merged[current.name];\n merged[current.name] = existing ? Object.assign({}, existing, current, {\n options: Object.assign({}, existing.options, current.options),\n data: Object.assign({}, existing.data, current.data)\n }) : current;\n return merged;\n }, {}); // IE11 does not support Object.values\n\n return Object.keys(merged).map(function (key) {\n return merged[key];\n });\n}","import { popperGenerator, detectOverflow } from \"./createPopper.js\";\nimport eventListeners from \"./modifiers/eventListeners.js\";\nimport popperOffsets from \"./modifiers/popperOffsets.js\";\nimport computeStyles from \"./modifiers/computeStyles.js\";\nimport applyStyles from \"./modifiers/applyStyles.js\";\nvar defaultModifiers = [eventListeners, popperOffsets, computeStyles, applyStyles];\nvar createPopper = /*#__PURE__*/popperGenerator({\n defaultModifiers: defaultModifiers\n}); // eslint-disable-next-line import/no-unused-modules\n\nexport { createPopper, popperGenerator, defaultModifiers, detectOverflow };","import { popperGenerator, detectOverflow } from \"./createPopper.js\";\nimport eventListeners from \"./modifiers/eventListeners.js\";\nimport popperOffsets from \"./modifiers/popperOffsets.js\";\nimport computeStyles from \"./modifiers/computeStyles.js\";\nimport applyStyles from \"./modifiers/applyStyles.js\";\nimport offset from \"./modifiers/offset.js\";\nimport flip from \"./modifiers/flip.js\";\nimport preventOverflow from \"./modifiers/preventOverflow.js\";\nimport arrow from \"./modifiers/arrow.js\";\nimport hide from \"./modifiers/hide.js\";\nvar defaultModifiers = [eventListeners, popperOffsets, computeStyles, applyStyles, offset, flip, preventOverflow, arrow, hide];\nvar createPopper = /*#__PURE__*/popperGenerator({\n defaultModifiers: defaultModifiers\n}); // eslint-disable-next-line import/no-unused-modules\n\nexport { createPopper, popperGenerator, defaultModifiers, detectOverflow }; // eslint-disable-next-line import/no-unused-modules\n\nexport { createPopper as createPopperLite } from \"./popper-lite.js\"; // eslint-disable-next-line import/no-unused-modules\n\nexport * from \"./modifiers/index.js\";","/**\n * --------------------------------------------------------------------------\n * Bootstrap dropdown.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport * as Popper from '@popperjs/core'\nimport BaseComponent from './base-component.js'\nimport EventHandler from './dom/event-handler.js'\nimport Manipulator from './dom/manipulator.js'\nimport SelectorEngine from './dom/selector-engine.js'\nimport {\n defineJQueryPlugin,\n execute,\n getElement,\n getNextActiveElement,\n isDisabled,\n isElement,\n isRTL,\n isVisible,\n noop\n} from './util/index.js'\n\n/**\n * Constants\n */\n\nconst NAME = 'dropdown'\nconst DATA_KEY = 'bs.dropdown'\nconst EVENT_KEY = `.${DATA_KEY}`\nconst DATA_API_KEY = '.data-api'\n\nconst ESCAPE_KEY = 'Escape'\nconst TAB_KEY = 'Tab'\nconst ARROW_UP_KEY = 'ArrowUp'\nconst ARROW_DOWN_KEY = 'ArrowDown'\nconst RIGHT_MOUSE_BUTTON = 2 // MouseEvent.button value for the secondary button, usually the right button\n\nconst EVENT_HIDE = `hide${EVENT_KEY}`\nconst EVENT_HIDDEN = `hidden${EVENT_KEY}`\nconst EVENT_SHOW = `show${EVENT_KEY}`\nconst EVENT_SHOWN = `shown${EVENT_KEY}`\nconst EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`\nconst EVENT_KEYDOWN_DATA_API = `keydown${EVENT_KEY}${DATA_API_KEY}`\nconst EVENT_KEYUP_DATA_API = `keyup${EVENT_KEY}${DATA_API_KEY}`\n\nconst CLASS_NAME_SHOW = 'show'\nconst CLASS_NAME_DROPUP = 'dropup'\nconst CLASS_NAME_DROPEND = 'dropend'\nconst CLASS_NAME_DROPSTART = 'dropstart'\nconst CLASS_NAME_DROPUP_CENTER = 'dropup-center'\nconst CLASS_NAME_DROPDOWN_CENTER = 'dropdown-center'\n\nconst SELECTOR_DATA_TOGGLE = '[data-bs-toggle=\"dropdown\"]:not(.disabled):not(:disabled)'\nconst SELECTOR_DATA_TOGGLE_SHOWN = `${SELECTOR_DATA_TOGGLE}.${CLASS_NAME_SHOW}`\nconst SELECTOR_MENU = '.dropdown-menu'\nconst SELECTOR_NAVBAR = '.navbar'\nconst SELECTOR_NAVBAR_NAV = '.navbar-nav'\nconst SELECTOR_VISIBLE_ITEMS = '.dropdown-menu .dropdown-item:not(.disabled):not(:disabled)'\n\nconst PLACEMENT_TOP = isRTL() ? 'top-end' : 'top-start'\nconst PLACEMENT_TOPEND = isRTL() ? 'top-start' : 'top-end'\nconst PLACEMENT_BOTTOM = isRTL() ? 'bottom-end' : 'bottom-start'\nconst PLACEMENT_BOTTOMEND = isRTL() ? 'bottom-start' : 'bottom-end'\nconst PLACEMENT_RIGHT = isRTL() ? 'left-start' : 'right-start'\nconst PLACEMENT_LEFT = isRTL() ? 'right-start' : 'left-start'\nconst PLACEMENT_TOPCENTER = 'top'\nconst PLACEMENT_BOTTOMCENTER = 'bottom'\n\nconst Default = {\n autoClose: true,\n boundary: 'clippingParents',\n display: 'dynamic',\n offset: [0, 2],\n popperConfig: null,\n reference: 'toggle'\n}\n\nconst DefaultType = {\n autoClose: '(boolean|string)',\n boundary: '(string|element)',\n display: 'string',\n offset: '(array|string|function)',\n popperConfig: '(null|object|function)',\n reference: '(string|element|object)'\n}\n\n/**\n * Class definition\n */\n\nclass Dropdown extends BaseComponent {\n constructor(element, config) {\n super(element, config)\n\n this._popper = null\n this._parent = this._element.parentNode // dropdown wrapper\n // TODO: v6 revert #37011 & change markup https://getbootstrap.com/docs/5.3/forms/input-group/\n this._menu = SelectorEngine.next(this._element, SELECTOR_MENU)[0] ||\n SelectorEngine.prev(this._element, SELECTOR_MENU)[0] ||\n SelectorEngine.findOne(SELECTOR_MENU, this._parent)\n this._inNavbar = this._detectNavbar()\n }\n\n // Getters\n static get Default() {\n return Default\n }\n\n static get DefaultType() {\n return DefaultType\n }\n\n static get NAME() {\n return NAME\n }\n\n // Public\n toggle() {\n return this._isShown() ? this.hide() : this.show()\n }\n\n show() {\n if (isDisabled(this._element) || this._isShown()) {\n return\n }\n\n const relatedTarget = {\n relatedTarget: this._element\n }\n\n const showEvent = EventHandler.trigger(this._element, EVENT_SHOW, relatedTarget)\n\n if (showEvent.defaultPrevented) {\n return\n }\n\n this._createPopper()\n\n // If this is a touch-enabled device we add extra\n // empty mouseover listeners to the body's immediate children;\n // only needed because of broken event delegation on iOS\n // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html\n if ('ontouchstart' in document.documentElement && !this._parent.closest(SELECTOR_NAVBAR_NAV)) {\n for (const element of [].concat(...document.body.children)) {\n EventHandler.on(element, 'mouseover', noop)\n }\n }\n\n this._element.focus()\n this._element.setAttribute('aria-expanded', true)\n\n this._menu.classList.add(CLASS_NAME_SHOW)\n this._element.classList.add(CLASS_NAME_SHOW)\n EventHandler.trigger(this._element, EVENT_SHOWN, relatedTarget)\n }\n\n hide() {\n if (isDisabled(this._element) || !this._isShown()) {\n return\n }\n\n const relatedTarget = {\n relatedTarget: this._element\n }\n\n this._completeHide(relatedTarget)\n }\n\n dispose() {\n if (this._popper) {\n this._popper.destroy()\n }\n\n super.dispose()\n }\n\n update() {\n this._inNavbar = this._detectNavbar()\n if (this._popper) {\n this._popper.update()\n }\n }\n\n // Private\n _completeHide(relatedTarget) {\n const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE, relatedTarget)\n if (hideEvent.defaultPrevented) {\n return\n }\n\n // If this is a touch-enabled device we remove the extra\n // empty mouseover listeners we added for iOS support\n if ('ontouchstart' in document.documentElement) {\n for (const element of [].concat(...document.body.children)) {\n EventHandler.off(element, 'mouseover', noop)\n }\n }\n\n if (this._popper) {\n this._popper.destroy()\n }\n\n this._menu.classList.remove(CLASS_NAME_SHOW)\n this._element.classList.remove(CLASS_NAME_SHOW)\n this._element.setAttribute('aria-expanded', 'false')\n Manipulator.removeDataAttribute(this._menu, 'popper')\n EventHandler.trigger(this._element, EVENT_HIDDEN, relatedTarget)\n }\n\n _getConfig(config) {\n config = super._getConfig(config)\n\n if (typeof config.reference === 'object' && !isElement(config.reference) &&\n typeof config.reference.getBoundingClientRect !== 'function'\n ) {\n // Popper virtual elements require a getBoundingClientRect method\n throw new TypeError(`${NAME.toUpperCase()}: Option \"reference\" provided type \"object\" without a required \"getBoundingClientRect\" method.`)\n }\n\n return config\n }\n\n _createPopper() {\n if (typeof Popper === 'undefined') {\n throw new TypeError('Bootstrap\\'s dropdowns require Popper (https://popper.js.org)')\n }\n\n let referenceElement = this._element\n\n if (this._config.reference === 'parent') {\n referenceElement = this._parent\n } else if (isElement(this._config.reference)) {\n referenceElement = getElement(this._config.reference)\n } else if (typeof this._config.reference === 'object') {\n referenceElement = this._config.reference\n }\n\n const popperConfig = this._getPopperConfig()\n this._popper = Popper.createPopper(referenceElement, this._menu, popperConfig)\n }\n\n _isShown() {\n return this._menu.classList.contains(CLASS_NAME_SHOW)\n }\n\n _getPlacement() {\n const parentDropdown = this._parent\n\n if (parentDropdown.classList.contains(CLASS_NAME_DROPEND)) {\n return PLACEMENT_RIGHT\n }\n\n if (parentDropdown.classList.contains(CLASS_NAME_DROPSTART)) {\n return PLACEMENT_LEFT\n }\n\n if (parentDropdown.classList.contains(CLASS_NAME_DROPUP_CENTER)) {\n return PLACEMENT_TOPCENTER\n }\n\n if (parentDropdown.classList.contains(CLASS_NAME_DROPDOWN_CENTER)) {\n return PLACEMENT_BOTTOMCENTER\n }\n\n // We need to trim the value because custom properties can also include spaces\n const isEnd = getComputedStyle(this._menu).getPropertyValue('--bs-position').trim() === 'end'\n\n if (parentDropdown.classList.contains(CLASS_NAME_DROPUP)) {\n return isEnd ? PLACEMENT_TOPEND : PLACEMENT_TOP\n }\n\n return isEnd ? PLACEMENT_BOTTOMEND : PLACEMENT_BOTTOM\n }\n\n _detectNavbar() {\n return this._element.closest(SELECTOR_NAVBAR) !== null\n }\n\n _getOffset() {\n const { offset } = this._config\n\n if (typeof offset === 'string') {\n return offset.split(',').map(value => Number.parseInt(value, 10))\n }\n\n if (typeof offset === 'function') {\n return popperData => offset(popperData, this._element)\n }\n\n return offset\n }\n\n _getPopperConfig() {\n const defaultBsPopperConfig = {\n placement: this._getPlacement(),\n modifiers: [{\n name: 'preventOverflow',\n options: {\n boundary: this._config.boundary\n }\n },\n {\n name: 'offset',\n options: {\n offset: this._getOffset()\n }\n }]\n }\n\n // Disable Popper if we have a static display or Dropdown is in Navbar\n if (this._inNavbar || this._config.display === 'static') {\n Manipulator.setDataAttribute(this._menu, 'popper', 'static') // TODO: v6 remove\n defaultBsPopperConfig.modifiers = [{\n name: 'applyStyles',\n enabled: false\n }]\n }\n\n return {\n ...defaultBsPopperConfig,\n ...execute(this._config.popperConfig, [defaultBsPopperConfig])\n }\n }\n\n _selectMenuItem({ key, target }) {\n const items = SelectorEngine.find(SELECTOR_VISIBLE_ITEMS, this._menu).filter(element => isVisible(element))\n\n if (!items.length) {\n return\n }\n\n // if target isn't included in items (e.g. when expanding the dropdown)\n // allow cycling to get the last item in case key equals ARROW_UP_KEY\n getNextActiveElement(items, target, key === ARROW_DOWN_KEY, !items.includes(target)).focus()\n }\n\n // Static\n static jQueryInterface(config) {\n return this.each(function () {\n const data = Dropdown.getOrCreateInstance(this, config)\n\n if (typeof config !== 'string') {\n return\n }\n\n if (typeof data[config] === 'undefined') {\n throw new TypeError(`No method named \"${config}\"`)\n }\n\n data[config]()\n })\n }\n\n static clearMenus(event) {\n if (event.button === RIGHT_MOUSE_BUTTON || (event.type === 'keyup' && event.key !== TAB_KEY)) {\n return\n }\n\n const openToggles = SelectorEngine.find(SELECTOR_DATA_TOGGLE_SHOWN)\n\n for (const toggle of openToggles) {\n const context = Dropdown.getInstance(toggle)\n if (!context || context._config.autoClose === false) {\n continue\n }\n\n const composedPath = event.composedPath()\n const isMenuTarget = composedPath.includes(context._menu)\n if (\n composedPath.includes(context._element) ||\n (context._config.autoClose === 'inside' && !isMenuTarget) ||\n (context._config.autoClose === 'outside' && isMenuTarget)\n ) {\n continue\n }\n\n // Tab navigation through the dropdown menu or events from contained inputs shouldn't close the menu\n if (context._menu.contains(event.target) && ((event.type === 'keyup' && event.key === TAB_KEY) || /input|select|option|textarea|form/i.test(event.target.tagName))) {\n continue\n }\n\n const relatedTarget = { relatedTarget: context._element }\n\n if (event.type === 'click') {\n relatedTarget.clickEvent = event\n }\n\n context._completeHide(relatedTarget)\n }\n }\n\n static dataApiKeydownHandler(event) {\n // If not an UP | DOWN | ESCAPE key => not a dropdown command\n // If input/textarea && if key is other than ESCAPE => not a dropdown command\n\n const isInput = /input|textarea/i.test(event.target.tagName)\n const isEscapeEvent = event.key === ESCAPE_KEY\n const isUpOrDownEvent = [ARROW_UP_KEY, ARROW_DOWN_KEY].includes(event.key)\n\n if (!isUpOrDownEvent && !isEscapeEvent) {\n return\n }\n\n if (isInput && !isEscapeEvent) {\n return\n }\n\n event.preventDefault()\n\n // TODO: v6 revert #37011 & change markup https://getbootstrap.com/docs/5.3/forms/input-group/\n const getToggleButton = this.matches(SELECTOR_DATA_TOGGLE) ?\n this :\n (SelectorEngine.prev(this, SELECTOR_DATA_TOGGLE)[0] ||\n SelectorEngine.next(this, SELECTOR_DATA_TOGGLE)[0] ||\n SelectorEngine.findOne(SELECTOR_DATA_TOGGLE, event.delegateTarget.parentNode))\n\n const instance = Dropdown.getOrCreateInstance(getToggleButton)\n\n if (isUpOrDownEvent) {\n event.stopPropagation()\n instance.show()\n instance._selectMenuItem(event)\n return\n }\n\n if (instance._isShown()) { // else is escape and we check if it is shown\n event.stopPropagation()\n instance.hide()\n getToggleButton.focus()\n }\n }\n}\n\n/**\n * Data API implementation\n */\n\nEventHandler.on(document, EVENT_KEYDOWN_DATA_API, SELECTOR_DATA_TOGGLE, Dropdown.dataApiKeydownHandler)\nEventHandler.on(document, EVENT_KEYDOWN_DATA_API, SELECTOR_MENU, Dropdown.dataApiKeydownHandler)\nEventHandler.on(document, EVENT_CLICK_DATA_API, Dropdown.clearMenus)\nEventHandler.on(document, EVENT_KEYUP_DATA_API, Dropdown.clearMenus)\nEventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {\n event.preventDefault()\n Dropdown.getOrCreateInstance(this).toggle()\n})\n\n/**\n * jQuery\n */\n\ndefineJQueryPlugin(Dropdown)\n\nexport default Dropdown\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap util/backdrop.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport EventHandler from '../dom/event-handler.js'\nimport Config from './config.js'\nimport { execute, executeAfterTransition, getElement, reflow } from './index.js'\n\n/**\n * Constants\n */\n\nconst NAME = 'backdrop'\nconst CLASS_NAME_FADE = 'fade'\nconst CLASS_NAME_SHOW = 'show'\nconst EVENT_MOUSEDOWN = `mousedown.bs.${NAME}`\n\nconst Default = {\n className: 'modal-backdrop',\n clickCallback: null,\n isAnimated: false,\n isVisible: true, // if false, we use the backdrop helper without adding any element to the dom\n rootElement: 'body' // give the choice to place backdrop under different elements\n}\n\nconst DefaultType = {\n className: 'string',\n clickCallback: '(function|null)',\n isAnimated: 'boolean',\n isVisible: 'boolean',\n rootElement: '(element|string)'\n}\n\n/**\n * Class definition\n */\n\nclass Backdrop extends Config {\n constructor(config) {\n super()\n this._config = this._getConfig(config)\n this._isAppended = false\n this._element = null\n }\n\n // Getters\n static get Default() {\n return Default\n }\n\n static get DefaultType() {\n return DefaultType\n }\n\n static get NAME() {\n return NAME\n }\n\n // Public\n show(callback) {\n if (!this._config.isVisible) {\n execute(callback)\n return\n }\n\n this._append()\n\n const element = this._getElement()\n if (this._config.isAnimated) {\n reflow(element)\n }\n\n element.classList.add(CLASS_NAME_SHOW)\n\n this._emulateAnimation(() => {\n execute(callback)\n })\n }\n\n hide(callback) {\n if (!this._config.isVisible) {\n execute(callback)\n return\n }\n\n this._getElement().classList.remove(CLASS_NAME_SHOW)\n\n this._emulateAnimation(() => {\n this.dispose()\n execute(callback)\n })\n }\n\n dispose() {\n if (!this._isAppended) {\n return\n }\n\n EventHandler.off(this._element, EVENT_MOUSEDOWN)\n\n this._element.remove()\n this._isAppended = false\n }\n\n // Private\n _getElement() {\n if (!this._element) {\n const backdrop = document.createElement('div')\n backdrop.className = this._config.className\n if (this._config.isAnimated) {\n backdrop.classList.add(CLASS_NAME_FADE)\n }\n\n this._element = backdrop\n }\n\n return this._element\n }\n\n _configAfterMerge(config) {\n // use getElement() with the default \"body\" to get a fresh Element on each instantiation\n config.rootElement = getElement(config.rootElement)\n return config\n }\n\n _append() {\n if (this._isAppended) {\n return\n }\n\n const element = this._getElement()\n this._config.rootElement.append(element)\n\n EventHandler.on(element, EVENT_MOUSEDOWN, () => {\n execute(this._config.clickCallback)\n })\n\n this._isAppended = true\n }\n\n _emulateAnimation(callback) {\n executeAfterTransition(callback, this._getElement(), this._config.isAnimated)\n }\n}\n\nexport default Backdrop\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap util/focustrap.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport EventHandler from '../dom/event-handler.js'\nimport SelectorEngine from '../dom/selector-engine.js'\nimport Config from './config.js'\n\n/**\n * Constants\n */\n\nconst NAME = 'focustrap'\nconst DATA_KEY = 'bs.focustrap'\nconst EVENT_KEY = `.${DATA_KEY}`\nconst EVENT_FOCUSIN = `focusin${EVENT_KEY}`\nconst EVENT_KEYDOWN_TAB = `keydown.tab${EVENT_KEY}`\n\nconst TAB_KEY = 'Tab'\nconst TAB_NAV_FORWARD = 'forward'\nconst TAB_NAV_BACKWARD = 'backward'\n\nconst Default = {\n autofocus: true,\n trapElement: null // The element to trap focus inside of\n}\n\nconst DefaultType = {\n autofocus: 'boolean',\n trapElement: 'element'\n}\n\n/**\n * Class definition\n */\n\nclass FocusTrap extends Config {\n constructor(config) {\n super()\n this._config = this._getConfig(config)\n this._isActive = false\n this._lastTabNavDirection = null\n }\n\n // Getters\n static get Default() {\n return Default\n }\n\n static get DefaultType() {\n return DefaultType\n }\n\n static get NAME() {\n return NAME\n }\n\n // Public\n activate() {\n if (this._isActive) {\n return\n }\n\n if (this._config.autofocus) {\n this._config.trapElement.focus()\n }\n\n EventHandler.off(document, EVENT_KEY) // guard against infinite focus loop\n EventHandler.on(document, EVENT_FOCUSIN, event => this._handleFocusin(event))\n EventHandler.on(document, EVENT_KEYDOWN_TAB, event => this._handleKeydown(event))\n\n this._isActive = true\n }\n\n deactivate() {\n if (!this._isActive) {\n return\n }\n\n this._isActive = false\n EventHandler.off(document, EVENT_KEY)\n }\n\n // Private\n _handleFocusin(event) {\n const { trapElement } = this._config\n\n if (event.target === document || event.target === trapElement || trapElement.contains(event.target)) {\n return\n }\n\n const elements = SelectorEngine.focusableChildren(trapElement)\n\n if (elements.length === 0) {\n trapElement.focus()\n } else if (this._lastTabNavDirection === TAB_NAV_BACKWARD) {\n elements[elements.length - 1].focus()\n } else {\n elements[0].focus()\n }\n }\n\n _handleKeydown(event) {\n if (event.key !== TAB_KEY) {\n return\n }\n\n this._lastTabNavDirection = event.shiftKey ? TAB_NAV_BACKWARD : TAB_NAV_FORWARD\n }\n}\n\nexport default FocusTrap\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap util/scrollBar.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport Manipulator from '../dom/manipulator.js'\nimport SelectorEngine from '../dom/selector-engine.js'\nimport { isElement } from './index.js'\n\n/**\n * Constants\n */\n\nconst SELECTOR_FIXED_CONTENT = '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top'\nconst SELECTOR_STICKY_CONTENT = '.sticky-top'\nconst PROPERTY_PADDING = 'padding-right'\nconst PROPERTY_MARGIN = 'margin-right'\n\n/**\n * Class definition\n */\n\nclass ScrollBarHelper {\n constructor() {\n this._element = document.body\n }\n\n // Public\n getWidth() {\n // https://developer.mozilla.org/en-US/docs/Web/API/Window/innerWidth#usage_notes\n const documentWidth = document.documentElement.clientWidth\n return Math.abs(window.innerWidth - documentWidth)\n }\n\n hide() {\n const width = this.getWidth()\n this._disableOverFlow()\n // give padding to element to balance the hidden scrollbar width\n this._setElementAttributes(this._element, PROPERTY_PADDING, calculatedValue => calculatedValue + width)\n // trick: We adjust positive paddingRight and negative marginRight to sticky-top elements to keep showing fullwidth\n this._setElementAttributes(SELECTOR_FIXED_CONTENT, PROPERTY_PADDING, calculatedValue => calculatedValue + width)\n this._setElementAttributes(SELECTOR_STICKY_CONTENT, PROPERTY_MARGIN, calculatedValue => calculatedValue - width)\n }\n\n reset() {\n this._resetElementAttributes(this._element, 'overflow')\n this._resetElementAttributes(this._element, PROPERTY_PADDING)\n this._resetElementAttributes(SELECTOR_FIXED_CONTENT, PROPERTY_PADDING)\n this._resetElementAttributes(SELECTOR_STICKY_CONTENT, PROPERTY_MARGIN)\n }\n\n isOverflowing() {\n return this.getWidth() > 0\n }\n\n // Private\n _disableOverFlow() {\n this._saveInitialAttribute(this._element, 'overflow')\n this._element.style.overflow = 'hidden'\n }\n\n _setElementAttributes(selector, styleProperty, callback) {\n const scrollbarWidth = this.getWidth()\n const manipulationCallBack = element => {\n if (element !== this._element && window.innerWidth > element.clientWidth + scrollbarWidth) {\n return\n }\n\n this._saveInitialAttribute(element, styleProperty)\n const calculatedValue = window.getComputedStyle(element).getPropertyValue(styleProperty)\n element.style.setProperty(styleProperty, `${callback(Number.parseFloat(calculatedValue))}px`)\n }\n\n this._applyManipulationCallback(selector, manipulationCallBack)\n }\n\n _saveInitialAttribute(element, styleProperty) {\n const actualValue = element.style.getPropertyValue(styleProperty)\n if (actualValue) {\n Manipulator.setDataAttribute(element, styleProperty, actualValue)\n }\n }\n\n _resetElementAttributes(selector, styleProperty) {\n const manipulationCallBack = element => {\n const value = Manipulator.getDataAttribute(element, styleProperty)\n // We only want to remove the property if the value is `null`; the value can also be zero\n if (value === null) {\n element.style.removeProperty(styleProperty)\n return\n }\n\n Manipulator.removeDataAttribute(element, styleProperty)\n element.style.setProperty(styleProperty, value)\n }\n\n this._applyManipulationCallback(selector, manipulationCallBack)\n }\n\n _applyManipulationCallback(selector, callBack) {\n if (isElement(selector)) {\n callBack(selector)\n return\n }\n\n for (const sel of SelectorEngine.find(selector, this._element)) {\n callBack(sel)\n }\n }\n}\n\nexport default ScrollBarHelper\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap modal.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport BaseComponent from './base-component.js'\nimport EventHandler from './dom/event-handler.js'\nimport SelectorEngine from './dom/selector-engine.js'\nimport Backdrop from './util/backdrop.js'\nimport { enableDismissTrigger } from './util/component-functions.js'\nimport FocusTrap from './util/focustrap.js'\nimport { defineJQueryPlugin, isRTL, isVisible, reflow } from './util/index.js'\nimport ScrollBarHelper from './util/scrollbar.js'\n\n/**\n * Constants\n */\n\nconst NAME = 'modal'\nconst DATA_KEY = 'bs.modal'\nconst EVENT_KEY = `.${DATA_KEY}`\nconst DATA_API_KEY = '.data-api'\nconst ESCAPE_KEY = 'Escape'\n\nconst EVENT_HIDE = `hide${EVENT_KEY}`\nconst EVENT_HIDE_PREVENTED = `hidePrevented${EVENT_KEY}`\nconst EVENT_HIDDEN = `hidden${EVENT_KEY}`\nconst EVENT_SHOW = `show${EVENT_KEY}`\nconst EVENT_SHOWN = `shown${EVENT_KEY}`\nconst EVENT_RESIZE = `resize${EVENT_KEY}`\nconst EVENT_CLICK_DISMISS = `click.dismiss${EVENT_KEY}`\nconst EVENT_MOUSEDOWN_DISMISS = `mousedown.dismiss${EVENT_KEY}`\nconst EVENT_KEYDOWN_DISMISS = `keydown.dismiss${EVENT_KEY}`\nconst EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`\n\nconst CLASS_NAME_OPEN = 'modal-open'\nconst CLASS_NAME_FADE = 'fade'\nconst CLASS_NAME_SHOW = 'show'\nconst CLASS_NAME_STATIC = 'modal-static'\n\nconst OPEN_SELECTOR = '.modal.show'\nconst SELECTOR_DIALOG = '.modal-dialog'\nconst SELECTOR_MODAL_BODY = '.modal-body'\nconst SELECTOR_DATA_TOGGLE = '[data-bs-toggle=\"modal\"]'\n\nconst Default = {\n backdrop: true,\n focus: true,\n keyboard: true\n}\n\nconst DefaultType = {\n backdrop: '(boolean|string)',\n focus: 'boolean',\n keyboard: 'boolean'\n}\n\n/**\n * Class definition\n */\n\nclass Modal extends BaseComponent {\n constructor(element, config) {\n super(element, config)\n\n this._dialog = SelectorEngine.findOne(SELECTOR_DIALOG, this._element)\n this._backdrop = this._initializeBackDrop()\n this._focustrap = this._initializeFocusTrap()\n this._isShown = false\n this._isTransitioning = false\n this._scrollBar = new ScrollBarHelper()\n\n this._addEventListeners()\n }\n\n // Getters\n static get Default() {\n return Default\n }\n\n static get DefaultType() {\n return DefaultType\n }\n\n static get NAME() {\n return NAME\n }\n\n // Public\n toggle(relatedTarget) {\n return this._isShown ? this.hide() : this.show(relatedTarget)\n }\n\n show(relatedTarget) {\n if (this._isShown || this._isTransitioning) {\n return\n }\n\n const showEvent = EventHandler.trigger(this._element, EVENT_SHOW, {\n relatedTarget\n })\n\n if (showEvent.defaultPrevented) {\n return\n }\n\n this._isShown = true\n this._isTransitioning = true\n\n this._scrollBar.hide()\n\n document.body.classList.add(CLASS_NAME_OPEN)\n\n this._adjustDialog()\n\n this._backdrop.show(() => this._showElement(relatedTarget))\n }\n\n hide() {\n if (!this._isShown || this._isTransitioning) {\n return\n }\n\n const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE)\n\n if (hideEvent.defaultPrevented) {\n return\n }\n\n this._isShown = false\n this._isTransitioning = true\n this._focustrap.deactivate()\n\n this._element.classList.remove(CLASS_NAME_SHOW)\n\n this._queueCallback(() => this._hideModal(), this._element, this._isAnimated())\n }\n\n dispose() {\n EventHandler.off(window, EVENT_KEY)\n EventHandler.off(this._dialog, EVENT_KEY)\n\n this._backdrop.dispose()\n this._focustrap.deactivate()\n\n super.dispose()\n }\n\n handleUpdate() {\n this._adjustDialog()\n }\n\n // Private\n _initializeBackDrop() {\n return new Backdrop({\n isVisible: Boolean(this._config.backdrop), // 'static' option will be translated to true, and booleans will keep their value,\n isAnimated: this._isAnimated()\n })\n }\n\n _initializeFocusTrap() {\n return new FocusTrap({\n trapElement: this._element\n })\n }\n\n _showElement(relatedTarget) {\n // try to append dynamic modal\n if (!document.body.contains(this._element)) {\n document.body.append(this._element)\n }\n\n this._element.style.display = 'block'\n this._element.removeAttribute('aria-hidden')\n this._element.setAttribute('aria-modal', true)\n this._element.setAttribute('role', 'dialog')\n this._element.scrollTop = 0\n\n const modalBody = SelectorEngine.findOne(SELECTOR_MODAL_BODY, this._dialog)\n if (modalBody) {\n modalBody.scrollTop = 0\n }\n\n reflow(this._element)\n\n this._element.classList.add(CLASS_NAME_SHOW)\n\n const transitionComplete = () => {\n if (this._config.focus) {\n this._focustrap.activate()\n }\n\n this._isTransitioning = false\n EventHandler.trigger(this._element, EVENT_SHOWN, {\n relatedTarget\n })\n }\n\n this._queueCallback(transitionComplete, this._dialog, this._isAnimated())\n }\n\n _addEventListeners() {\n EventHandler.on(this._element, EVENT_KEYDOWN_DISMISS, event => {\n if (event.key !== ESCAPE_KEY) {\n return\n }\n\n if (this._config.keyboard) {\n this.hide()\n return\n }\n\n this._triggerBackdropTransition()\n })\n\n EventHandler.on(window, EVENT_RESIZE, () => {\n if (this._isShown && !this._isTransitioning) {\n this._adjustDialog()\n }\n })\n\n EventHandler.on(this._element, EVENT_MOUSEDOWN_DISMISS, event => {\n // a bad trick to segregate clicks that may start inside dialog but end outside, and avoid listen to scrollbar clicks\n EventHandler.one(this._element, EVENT_CLICK_DISMISS, event2 => {\n if (this._element !== event.target || this._element !== event2.target) {\n return\n }\n\n if (this._config.backdrop === 'static') {\n this._triggerBackdropTransition()\n return\n }\n\n if (this._config.backdrop) {\n this.hide()\n }\n })\n })\n }\n\n _hideModal() {\n this._element.style.display = 'none'\n this._element.setAttribute('aria-hidden', true)\n this._element.removeAttribute('aria-modal')\n this._element.removeAttribute('role')\n this._isTransitioning = false\n\n this._backdrop.hide(() => {\n document.body.classList.remove(CLASS_NAME_OPEN)\n this._resetAdjustments()\n this._scrollBar.reset()\n EventHandler.trigger(this._element, EVENT_HIDDEN)\n })\n }\n\n _isAnimated() {\n return this._element.classList.contains(CLASS_NAME_FADE)\n }\n\n _triggerBackdropTransition() {\n const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE_PREVENTED)\n if (hideEvent.defaultPrevented) {\n return\n }\n\n const isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight\n const initialOverflowY = this._element.style.overflowY\n // return if the following background transition hasn't yet completed\n if (initialOverflowY === 'hidden' || this._element.classList.contains(CLASS_NAME_STATIC)) {\n return\n }\n\n if (!isModalOverflowing) {\n this._element.style.overflowY = 'hidden'\n }\n\n this._element.classList.add(CLASS_NAME_STATIC)\n this._queueCallback(() => {\n this._element.classList.remove(CLASS_NAME_STATIC)\n this._queueCallback(() => {\n this._element.style.overflowY = initialOverflowY\n }, this._dialog)\n }, this._dialog)\n\n this._element.focus()\n }\n\n /**\n * The following methods are used to handle overflowing modals\n */\n\n _adjustDialog() {\n const isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight\n const scrollbarWidth = this._scrollBar.getWidth()\n const isBodyOverflowing = scrollbarWidth > 0\n\n if (isBodyOverflowing && !isModalOverflowing) {\n const property = isRTL() ? 'paddingLeft' : 'paddingRight'\n this._element.style[property] = `${scrollbarWidth}px`\n }\n\n if (!isBodyOverflowing && isModalOverflowing) {\n const property = isRTL() ? 'paddingRight' : 'paddingLeft'\n this._element.style[property] = `${scrollbarWidth}px`\n }\n }\n\n _resetAdjustments() {\n this._element.style.paddingLeft = ''\n this._element.style.paddingRight = ''\n }\n\n // Static\n static jQueryInterface(config, relatedTarget) {\n return this.each(function () {\n const data = Modal.getOrCreateInstance(this, config)\n\n if (typeof config !== 'string') {\n return\n }\n\n if (typeof data[config] === 'undefined') {\n throw new TypeError(`No method named \"${config}\"`)\n }\n\n data[config](relatedTarget)\n })\n }\n}\n\n/**\n * Data API implementation\n */\n\nEventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {\n const target = SelectorEngine.getElementFromSelector(this)\n\n if (['A', 'AREA'].includes(this.tagName)) {\n event.preventDefault()\n }\n\n EventHandler.one(target, EVENT_SHOW, showEvent => {\n if (showEvent.defaultPrevented) {\n // only register focus restorer if modal will actually get shown\n return\n }\n\n EventHandler.one(target, EVENT_HIDDEN, () => {\n if (isVisible(this)) {\n this.focus()\n }\n })\n })\n\n // avoid conflict when clicking modal toggler while another one is open\n const alreadyOpen = SelectorEngine.findOne(OPEN_SELECTOR)\n if (alreadyOpen) {\n Modal.getInstance(alreadyOpen).hide()\n }\n\n const data = Modal.getOrCreateInstance(target)\n\n data.toggle(this)\n})\n\nenableDismissTrigger(Modal)\n\n/**\n * jQuery\n */\n\ndefineJQueryPlugin(Modal)\n\nexport default Modal\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap offcanvas.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport BaseComponent from './base-component.js'\nimport EventHandler from './dom/event-handler.js'\nimport SelectorEngine from './dom/selector-engine.js'\nimport Backdrop from './util/backdrop.js'\nimport { enableDismissTrigger } from './util/component-functions.js'\nimport FocusTrap from './util/focustrap.js'\nimport {\n defineJQueryPlugin,\n isDisabled,\n isVisible\n} from './util/index.js'\nimport ScrollBarHelper from './util/scrollbar.js'\n\n/**\n * Constants\n */\n\nconst NAME = 'offcanvas'\nconst DATA_KEY = 'bs.offcanvas'\nconst EVENT_KEY = `.${DATA_KEY}`\nconst DATA_API_KEY = '.data-api'\nconst EVENT_LOAD_DATA_API = `load${EVENT_KEY}${DATA_API_KEY}`\nconst ESCAPE_KEY = 'Escape'\n\nconst CLASS_NAME_SHOW = 'show'\nconst CLASS_NAME_SHOWING = 'showing'\nconst CLASS_NAME_HIDING = 'hiding'\nconst CLASS_NAME_BACKDROP = 'offcanvas-backdrop'\nconst OPEN_SELECTOR = '.offcanvas.show'\n\nconst EVENT_SHOW = `show${EVENT_KEY}`\nconst EVENT_SHOWN = `shown${EVENT_KEY}`\nconst EVENT_HIDE = `hide${EVENT_KEY}`\nconst EVENT_HIDE_PREVENTED = `hidePrevented${EVENT_KEY}`\nconst EVENT_HIDDEN = `hidden${EVENT_KEY}`\nconst EVENT_RESIZE = `resize${EVENT_KEY}`\nconst EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`\nconst EVENT_KEYDOWN_DISMISS = `keydown.dismiss${EVENT_KEY}`\n\nconst SELECTOR_DATA_TOGGLE = '[data-bs-toggle=\"offcanvas\"]'\n\nconst Default = {\n backdrop: true,\n keyboard: true,\n scroll: false\n}\n\nconst DefaultType = {\n backdrop: '(boolean|string)',\n keyboard: 'boolean',\n scroll: 'boolean'\n}\n\n/**\n * Class definition\n */\n\nclass Offcanvas extends BaseComponent {\n constructor(element, config) {\n super(element, config)\n\n this._isShown = false\n this._backdrop = this._initializeBackDrop()\n this._focustrap = this._initializeFocusTrap()\n this._addEventListeners()\n }\n\n // Getters\n static get Default() {\n return Default\n }\n\n static get DefaultType() {\n return DefaultType\n }\n\n static get NAME() {\n return NAME\n }\n\n // Public\n toggle(relatedTarget) {\n return this._isShown ? this.hide() : this.show(relatedTarget)\n }\n\n show(relatedTarget) {\n if (this._isShown) {\n return\n }\n\n const showEvent = EventHandler.trigger(this._element, EVENT_SHOW, { relatedTarget })\n\n if (showEvent.defaultPrevented) {\n return\n }\n\n this._isShown = true\n this._backdrop.show()\n\n if (!this._config.scroll) {\n new ScrollBarHelper().hide()\n }\n\n this._element.setAttribute('aria-modal', true)\n this._element.setAttribute('role', 'dialog')\n this._element.classList.add(CLASS_NAME_SHOWING)\n\n const completeCallBack = () => {\n if (!this._config.scroll || this._config.backdrop) {\n this._focustrap.activate()\n }\n\n this._element.classList.add(CLASS_NAME_SHOW)\n this._element.classList.remove(CLASS_NAME_SHOWING)\n EventHandler.trigger(this._element, EVENT_SHOWN, { relatedTarget })\n }\n\n this._queueCallback(completeCallBack, this._element, true)\n }\n\n hide() {\n if (!this._isShown) {\n return\n }\n\n const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE)\n\n if (hideEvent.defaultPrevented) {\n return\n }\n\n this._focustrap.deactivate()\n this._element.blur()\n this._isShown = false\n this._element.classList.add(CLASS_NAME_HIDING)\n this._backdrop.hide()\n\n const completeCallback = () => {\n this._element.classList.remove(CLASS_NAME_SHOW, CLASS_NAME_HIDING)\n this._element.removeAttribute('aria-modal')\n this._element.removeAttribute('role')\n\n if (!this._config.scroll) {\n new ScrollBarHelper().reset()\n }\n\n EventHandler.trigger(this._element, EVENT_HIDDEN)\n }\n\n this._queueCallback(completeCallback, this._element, true)\n }\n\n dispose() {\n this._backdrop.dispose()\n this._focustrap.deactivate()\n super.dispose()\n }\n\n // Private\n _initializeBackDrop() {\n const clickCallback = () => {\n if (this._config.backdrop === 'static') {\n EventHandler.trigger(this._element, EVENT_HIDE_PREVENTED)\n return\n }\n\n this.hide()\n }\n\n // 'static' option will be translated to true, and booleans will keep their value\n const isVisible = Boolean(this._config.backdrop)\n\n return new Backdrop({\n className: CLASS_NAME_BACKDROP,\n isVisible,\n isAnimated: true,\n rootElement: this._element.parentNode,\n clickCallback: isVisible ? clickCallback : null\n })\n }\n\n _initializeFocusTrap() {\n return new FocusTrap({\n trapElement: this._element\n })\n }\n\n _addEventListeners() {\n EventHandler.on(this._element, EVENT_KEYDOWN_DISMISS, event => {\n if (event.key !== ESCAPE_KEY) {\n return\n }\n\n if (this._config.keyboard) {\n this.hide()\n return\n }\n\n EventHandler.trigger(this._element, EVENT_HIDE_PREVENTED)\n })\n }\n\n // Static\n static jQueryInterface(config) {\n return this.each(function () {\n const data = Offcanvas.getOrCreateInstance(this, config)\n\n if (typeof config !== 'string') {\n return\n }\n\n if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {\n throw new TypeError(`No method named \"${config}\"`)\n }\n\n data[config](this)\n })\n }\n}\n\n/**\n * Data API implementation\n */\n\nEventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {\n const target = SelectorEngine.getElementFromSelector(this)\n\n if (['A', 'AREA'].includes(this.tagName)) {\n event.preventDefault()\n }\n\n if (isDisabled(this)) {\n return\n }\n\n EventHandler.one(target, EVENT_HIDDEN, () => {\n // focus on trigger when it is closed\n if (isVisible(this)) {\n this.focus()\n }\n })\n\n // avoid conflict when clicking a toggler of an offcanvas, while another is open\n const alreadyOpen = SelectorEngine.findOne(OPEN_SELECTOR)\n if (alreadyOpen && alreadyOpen !== target) {\n Offcanvas.getInstance(alreadyOpen).hide()\n }\n\n const data = Offcanvas.getOrCreateInstance(target)\n data.toggle(this)\n})\n\nEventHandler.on(window, EVENT_LOAD_DATA_API, () => {\n for (const selector of SelectorEngine.find(OPEN_SELECTOR)) {\n Offcanvas.getOrCreateInstance(selector).show()\n }\n})\n\nEventHandler.on(window, EVENT_RESIZE, () => {\n for (const element of SelectorEngine.find('[aria-modal][class*=show][class*=offcanvas-]')) {\n if (getComputedStyle(element).position !== 'fixed') {\n Offcanvas.getOrCreateInstance(element).hide()\n }\n }\n})\n\nenableDismissTrigger(Offcanvas)\n\n/**\n * jQuery\n */\n\ndefineJQueryPlugin(Offcanvas)\n\nexport default Offcanvas\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap util/sanitizer.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\n// js-docs-start allow-list\nconst ARIA_ATTRIBUTE_PATTERN = /^aria-[\\w-]*$/i\n\nexport const DefaultAllowlist = {\n // Global attributes allowed on any supplied element below.\n '*': ['class', 'dir', 'id', 'lang', 'role', ARIA_ATTRIBUTE_PATTERN],\n a: ['target', 'href', 'title', 'rel'],\n area: [],\n b: [],\n br: [],\n col: [],\n code: [],\n div: [],\n em: [],\n hr: [],\n h1: [],\n h2: [],\n h3: [],\n h4: [],\n h5: [],\n h6: [],\n i: [],\n img: ['src', 'srcset', 'alt', 'title', 'width', 'height'],\n li: [],\n ol: [],\n p: [],\n pre: [],\n s: [],\n small: [],\n span: [],\n sub: [],\n sup: [],\n strong: [],\n u: [],\n ul: []\n}\n// js-docs-end allow-list\n\nconst uriAttributes = new Set([\n 'background',\n 'cite',\n 'href',\n 'itemtype',\n 'longdesc',\n 'poster',\n 'src',\n 'xlink:href'\n])\n\n/**\n * A pattern that recognizes URLs that are safe wrt. XSS in URL navigation\n * contexts.\n *\n * Shout-out to Angular https://github.com/angular/angular/blob/15.2.8/packages/core/src/sanitization/url_sanitizer.ts#L38\n */\n// eslint-disable-next-line unicorn/better-regex\nconst SAFE_URL_PATTERN = /^(?!javascript:)(?:[a-z0-9+.-]+:|[^&:/?#]*(?:[/?#]|$))/i\n\nconst allowedAttribute = (attribute, allowedAttributeList) => {\n const attributeName = attribute.nodeName.toLowerCase()\n\n if (allowedAttributeList.includes(attributeName)) {\n if (uriAttributes.has(attributeName)) {\n return Boolean(SAFE_URL_PATTERN.test(attribute.nodeValue))\n }\n\n return true\n }\n\n // Check if a regular expression validates the attribute.\n return allowedAttributeList.filter(attributeRegex => attributeRegex instanceof RegExp)\n .some(regex => regex.test(attributeName))\n}\n\nexport function sanitizeHtml(unsafeHtml, allowList, sanitizeFunction) {\n if (!unsafeHtml.length) {\n return unsafeHtml\n }\n\n if (sanitizeFunction && typeof sanitizeFunction === 'function') {\n return sanitizeFunction(unsafeHtml)\n }\n\n const domParser = new window.DOMParser()\n const createdDocument = domParser.parseFromString(unsafeHtml, 'text/html')\n const elements = [].concat(...createdDocument.body.querySelectorAll('*'))\n\n for (const element of elements) {\n const elementName = element.nodeName.toLowerCase()\n\n if (!Object.keys(allowList).includes(elementName)) {\n element.remove()\n continue\n }\n\n const attributeList = [].concat(...element.attributes)\n const allowedAttributes = [].concat(allowList['*'] || [], allowList[elementName] || [])\n\n for (const attribute of attributeList) {\n if (!allowedAttribute(attribute, allowedAttributes)) {\n element.removeAttribute(attribute.nodeName)\n }\n }\n }\n\n return createdDocument.body.innerHTML\n}\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap util/template-factory.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport SelectorEngine from '../dom/selector-engine.js'\nimport Config from './config.js'\nimport { DefaultAllowlist, sanitizeHtml } from './sanitizer.js'\nimport { execute, getElement, isElement } from './index.js'\n\n/**\n * Constants\n */\n\nconst NAME = 'TemplateFactory'\n\nconst Default = {\n allowList: DefaultAllowlist,\n content: {}, // { selector : text , selector2 : text2 , }\n extraClass: '',\n html: false,\n sanitize: true,\n sanitizeFn: null,\n template: '
'\n}\n\nconst DefaultType = {\n allowList: 'object',\n content: 'object',\n extraClass: '(string|function)',\n html: 'boolean',\n sanitize: 'boolean',\n sanitizeFn: '(null|function)',\n template: 'string'\n}\n\nconst DefaultContentType = {\n entry: '(string|element|function|null)',\n selector: '(string|element)'\n}\n\n/**\n * Class definition\n */\n\nclass TemplateFactory extends Config {\n constructor(config) {\n super()\n this._config = this._getConfig(config)\n }\n\n // Getters\n static get Default() {\n return Default\n }\n\n static get DefaultType() {\n return DefaultType\n }\n\n static get NAME() {\n return NAME\n }\n\n // Public\n getContent() {\n return Object.values(this._config.content)\n .map(config => this._resolvePossibleFunction(config))\n .filter(Boolean)\n }\n\n hasContent() {\n return this.getContent().length > 0\n }\n\n changeContent(content) {\n this._checkContent(content)\n this._config.content = { ...this._config.content, ...content }\n return this\n }\n\n toHtml() {\n const templateWrapper = document.createElement('div')\n templateWrapper.innerHTML = this._maybeSanitize(this._config.template)\n\n for (const [selector, text] of Object.entries(this._config.content)) {\n this._setContent(templateWrapper, text, selector)\n }\n\n const template = templateWrapper.children[0]\n const extraClass = this._resolvePossibleFunction(this._config.extraClass)\n\n if (extraClass) {\n template.classList.add(...extraClass.split(' '))\n }\n\n return template\n }\n\n // Private\n _typeCheckConfig(config) {\n super._typeCheckConfig(config)\n this._checkContent(config.content)\n }\n\n _checkContent(arg) {\n for (const [selector, content] of Object.entries(arg)) {\n super._typeCheckConfig({ selector, entry: content }, DefaultContentType)\n }\n }\n\n _setContent(template, content, selector) {\n const templateElement = SelectorEngine.findOne(selector, template)\n\n if (!templateElement) {\n return\n }\n\n content = this._resolvePossibleFunction(content)\n\n if (!content) {\n templateElement.remove()\n return\n }\n\n if (isElement(content)) {\n this._putElementInTemplate(getElement(content), templateElement)\n return\n }\n\n if (this._config.html) {\n templateElement.innerHTML = this._maybeSanitize(content)\n return\n }\n\n templateElement.textContent = content\n }\n\n _maybeSanitize(arg) {\n return this._config.sanitize ? sanitizeHtml(arg, this._config.allowList, this._config.sanitizeFn) : arg\n }\n\n _resolvePossibleFunction(arg) {\n return execute(arg, [this])\n }\n\n _putElementInTemplate(element, templateElement) {\n if (this._config.html) {\n templateElement.innerHTML = ''\n templateElement.append(element)\n return\n }\n\n templateElement.textContent = element.textContent\n }\n}\n\nexport default TemplateFactory\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap tooltip.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport * as Popper from '@popperjs/core'\nimport BaseComponent from './base-component.js'\nimport EventHandler from './dom/event-handler.js'\nimport Manipulator from './dom/manipulator.js'\nimport { defineJQueryPlugin, execute, findShadowRoot, getElement, getUID, isRTL, noop } from './util/index.js'\nimport { DefaultAllowlist } from './util/sanitizer.js'\nimport TemplateFactory from './util/template-factory.js'\n\n/**\n * Constants\n */\n\nconst NAME = 'tooltip'\nconst DISALLOWED_ATTRIBUTES = new Set(['sanitize', 'allowList', 'sanitizeFn'])\n\nconst CLASS_NAME_FADE = 'fade'\nconst CLASS_NAME_MODAL = 'modal'\nconst CLASS_NAME_SHOW = 'show'\n\nconst SELECTOR_TOOLTIP_INNER = '.tooltip-inner'\nconst SELECTOR_MODAL = `.${CLASS_NAME_MODAL}`\n\nconst EVENT_MODAL_HIDE = 'hide.bs.modal'\n\nconst TRIGGER_HOVER = 'hover'\nconst TRIGGER_FOCUS = 'focus'\nconst TRIGGER_CLICK = 'click'\nconst TRIGGER_MANUAL = 'manual'\n\nconst EVENT_HIDE = 'hide'\nconst EVENT_HIDDEN = 'hidden'\nconst EVENT_SHOW = 'show'\nconst EVENT_SHOWN = 'shown'\nconst EVENT_INSERTED = 'inserted'\nconst EVENT_CLICK = 'click'\nconst EVENT_FOCUSIN = 'focusin'\nconst EVENT_FOCUSOUT = 'focusout'\nconst EVENT_MOUSEENTER = 'mouseenter'\nconst EVENT_MOUSELEAVE = 'mouseleave'\n\nconst AttachmentMap = {\n AUTO: 'auto',\n TOP: 'top',\n RIGHT: isRTL() ? 'left' : 'right',\n BOTTOM: 'bottom',\n LEFT: isRTL() ? 'right' : 'left'\n}\n\nconst Default = {\n allowList: DefaultAllowlist,\n animation: true,\n boundary: 'clippingParents',\n container: false,\n customClass: '',\n delay: 0,\n fallbackPlacements: ['top', 'right', 'bottom', 'left'],\n html: false,\n offset: [0, 6],\n placement: 'top',\n popperConfig: null,\n sanitize: true,\n sanitizeFn: null,\n selector: false,\n template: '
' +\n '
' +\n '
' +\n '
',\n title: '',\n trigger: 'hover focus'\n}\n\nconst DefaultType = {\n allowList: 'object',\n animation: 'boolean',\n boundary: '(string|element)',\n container: '(string|element|boolean)',\n customClass: '(string|function)',\n delay: '(number|object)',\n fallbackPlacements: 'array',\n html: 'boolean',\n offset: '(array|string|function)',\n placement: '(string|function)',\n popperConfig: '(null|object|function)',\n sanitize: 'boolean',\n sanitizeFn: '(null|function)',\n selector: '(string|boolean)',\n template: 'string',\n title: '(string|element|function)',\n trigger: 'string'\n}\n\n/**\n * Class definition\n */\n\nclass Tooltip extends BaseComponent {\n constructor(element, config) {\n if (typeof Popper === 'undefined') {\n throw new TypeError('Bootstrap\\'s tooltips require Popper (https://popper.js.org)')\n }\n\n super(element, config)\n\n // Private\n this._isEnabled = true\n this._timeout = 0\n this._isHovered = null\n this._activeTrigger = {}\n this._popper = null\n this._templateFactory = null\n this._newContent = null\n\n // Protected\n this.tip = null\n\n this._setListeners()\n\n if (!this._config.selector) {\n this._fixTitle()\n }\n }\n\n // Getters\n static get Default() {\n return Default\n }\n\n static get DefaultType() {\n return DefaultType\n }\n\n static get NAME() {\n return NAME\n }\n\n // Public\n enable() {\n this._isEnabled = true\n }\n\n disable() {\n this._isEnabled = false\n }\n\n toggleEnabled() {\n this._isEnabled = !this._isEnabled\n }\n\n toggle() {\n if (!this._isEnabled) {\n return\n }\n\n this._activeTrigger.click = !this._activeTrigger.click\n if (this._isShown()) {\n this._leave()\n return\n }\n\n this._enter()\n }\n\n dispose() {\n clearTimeout(this._timeout)\n\n EventHandler.off(this._element.closest(SELECTOR_MODAL), EVENT_MODAL_HIDE, this._hideModalHandler)\n\n if (this._element.getAttribute('data-bs-original-title')) {\n this._element.setAttribute('title', this._element.getAttribute('data-bs-original-title'))\n }\n\n this._disposePopper()\n super.dispose()\n }\n\n show() {\n if (this._element.style.display === 'none') {\n throw new Error('Please use show on visible elements')\n }\n\n if (!(this._isWithContent() && this._isEnabled)) {\n return\n }\n\n const showEvent = EventHandler.trigger(this._element, this.constructor.eventName(EVENT_SHOW))\n const shadowRoot = findShadowRoot(this._element)\n const isInTheDom = (shadowRoot || this._element.ownerDocument.documentElement).contains(this._element)\n\n if (showEvent.defaultPrevented || !isInTheDom) {\n return\n }\n\n // TODO: v6 remove this or make it optional\n this._disposePopper()\n\n const tip = this._getTipElement()\n\n this._element.setAttribute('aria-describedby', tip.getAttribute('id'))\n\n const { container } = this._config\n\n if (!this._element.ownerDocument.documentElement.contains(this.tip)) {\n container.append(tip)\n EventHandler.trigger(this._element, this.constructor.eventName(EVENT_INSERTED))\n }\n\n this._popper = this._createPopper(tip)\n\n tip.classList.add(CLASS_NAME_SHOW)\n\n // If this is a touch-enabled device we add extra\n // empty mouseover listeners to the body's immediate children;\n // only needed because of broken event delegation on iOS\n // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html\n if ('ontouchstart' in document.documentElement) {\n for (const element of [].concat(...document.body.children)) {\n EventHandler.on(element, 'mouseover', noop)\n }\n }\n\n const complete = () => {\n EventHandler.trigger(this._element, this.constructor.eventName(EVENT_SHOWN))\n\n if (this._isHovered === false) {\n this._leave()\n }\n\n this._isHovered = false\n }\n\n this._queueCallback(complete, this.tip, this._isAnimated())\n }\n\n hide() {\n if (!this._isShown()) {\n return\n }\n\n const hideEvent = EventHandler.trigger(this._element, this.constructor.eventName(EVENT_HIDE))\n if (hideEvent.defaultPrevented) {\n return\n }\n\n const tip = this._getTipElement()\n tip.classList.remove(CLASS_NAME_SHOW)\n\n // If this is a touch-enabled device we remove the extra\n // empty mouseover listeners we added for iOS support\n if ('ontouchstart' in document.documentElement) {\n for (const element of [].concat(...document.body.children)) {\n EventHandler.off(element, 'mouseover', noop)\n }\n }\n\n this._activeTrigger[TRIGGER_CLICK] = false\n this._activeTrigger[TRIGGER_FOCUS] = false\n this._activeTrigger[TRIGGER_HOVER] = false\n this._isHovered = null // it is a trick to support manual triggering\n\n const complete = () => {\n if (this._isWithActiveTrigger()) {\n return\n }\n\n if (!this._isHovered) {\n this._disposePopper()\n }\n\n this._element.removeAttribute('aria-describedby')\n EventHandler.trigger(this._element, this.constructor.eventName(EVENT_HIDDEN))\n }\n\n this._queueCallback(complete, this.tip, this._isAnimated())\n }\n\n update() {\n if (this._popper) {\n this._popper.update()\n }\n }\n\n // Protected\n _isWithContent() {\n return Boolean(this._getTitle())\n }\n\n _getTipElement() {\n if (!this.tip) {\n this.tip = this._createTipElement(this._newContent || this._getContentForTemplate())\n }\n\n return this.tip\n }\n\n _createTipElement(content) {\n const tip = this._getTemplateFactory(content).toHtml()\n\n // TODO: remove this check in v6\n if (!tip) {\n return null\n }\n\n tip.classList.remove(CLASS_NAME_FADE, CLASS_NAME_SHOW)\n // TODO: v6 the following can be achieved with CSS only\n tip.classList.add(`bs-${this.constructor.NAME}-auto`)\n\n const tipId = getUID(this.constructor.NAME).toString()\n\n tip.setAttribute('id', tipId)\n\n if (this._isAnimated()) {\n tip.classList.add(CLASS_NAME_FADE)\n }\n\n return tip\n }\n\n setContent(content) {\n this._newContent = content\n if (this._isShown()) {\n this._disposePopper()\n this.show()\n }\n }\n\n _getTemplateFactory(content) {\n if (this._templateFactory) {\n this._templateFactory.changeContent(content)\n } else {\n this._templateFactory = new TemplateFactory({\n ...this._config,\n // the `content` var has to be after `this._config`\n // to override config.content in case of popover\n content,\n extraClass: this._resolvePossibleFunction(this._config.customClass)\n })\n }\n\n return this._templateFactory\n }\n\n _getContentForTemplate() {\n return {\n [SELECTOR_TOOLTIP_INNER]: this._getTitle()\n }\n }\n\n _getTitle() {\n return this._resolvePossibleFunction(this._config.title) || this._element.getAttribute('data-bs-original-title')\n }\n\n // Private\n _initializeOnDelegatedTarget(event) {\n return this.constructor.getOrCreateInstance(event.delegateTarget, this._getDelegateConfig())\n }\n\n _isAnimated() {\n return this._config.animation || (this.tip && this.tip.classList.contains(CLASS_NAME_FADE))\n }\n\n _isShown() {\n return this.tip && this.tip.classList.contains(CLASS_NAME_SHOW)\n }\n\n _createPopper(tip) {\n const placement = execute(this._config.placement, [this, tip, this._element])\n const attachment = AttachmentMap[placement.toUpperCase()]\n return Popper.createPopper(this._element, tip, this._getPopperConfig(attachment))\n }\n\n _getOffset() {\n const { offset } = this._config\n\n if (typeof offset === 'string') {\n return offset.split(',').map(value => Number.parseInt(value, 10))\n }\n\n if (typeof offset === 'function') {\n return popperData => offset(popperData, this._element)\n }\n\n return offset\n }\n\n _resolvePossibleFunction(arg) {\n return execute(arg, [this._element])\n }\n\n _getPopperConfig(attachment) {\n const defaultBsPopperConfig = {\n placement: attachment,\n modifiers: [\n {\n name: 'flip',\n options: {\n fallbackPlacements: this._config.fallbackPlacements\n }\n },\n {\n name: 'offset',\n options: {\n offset: this._getOffset()\n }\n },\n {\n name: 'preventOverflow',\n options: {\n boundary: this._config.boundary\n }\n },\n {\n name: 'arrow',\n options: {\n element: `.${this.constructor.NAME}-arrow`\n }\n },\n {\n name: 'preSetPlacement',\n enabled: true,\n phase: 'beforeMain',\n fn: data => {\n // Pre-set Popper's placement attribute in order to read the arrow sizes properly.\n // Otherwise, Popper mixes up the width and height dimensions since the initial arrow style is for top placement\n this._getTipElement().setAttribute('data-popper-placement', data.state.placement)\n }\n }\n ]\n }\n\n return {\n ...defaultBsPopperConfig,\n ...execute(this._config.popperConfig, [defaultBsPopperConfig])\n }\n }\n\n _setListeners() {\n const triggers = this._config.trigger.split(' ')\n\n for (const trigger of triggers) {\n if (trigger === 'click') {\n EventHandler.on(this._element, this.constructor.eventName(EVENT_CLICK), this._config.selector, event => {\n const context = this._initializeOnDelegatedTarget(event)\n context.toggle()\n })\n } else if (trigger !== TRIGGER_MANUAL) {\n const eventIn = trigger === TRIGGER_HOVER ?\n this.constructor.eventName(EVENT_MOUSEENTER) :\n this.constructor.eventName(EVENT_FOCUSIN)\n const eventOut = trigger === TRIGGER_HOVER ?\n this.constructor.eventName(EVENT_MOUSELEAVE) :\n this.constructor.eventName(EVENT_FOCUSOUT)\n\n EventHandler.on(this._element, eventIn, this._config.selector, event => {\n const context = this._initializeOnDelegatedTarget(event)\n context._activeTrigger[event.type === 'focusin' ? TRIGGER_FOCUS : TRIGGER_HOVER] = true\n context._enter()\n })\n EventHandler.on(this._element, eventOut, this._config.selector, event => {\n const context = this._initializeOnDelegatedTarget(event)\n context._activeTrigger[event.type === 'focusout' ? TRIGGER_FOCUS : TRIGGER_HOVER] =\n context._element.contains(event.relatedTarget)\n\n context._leave()\n })\n }\n }\n\n this._hideModalHandler = () => {\n if (this._element) {\n this.hide()\n }\n }\n\n EventHandler.on(this._element.closest(SELECTOR_MODAL), EVENT_MODAL_HIDE, this._hideModalHandler)\n }\n\n _fixTitle() {\n const title = this._element.getAttribute('title')\n\n if (!title) {\n return\n }\n\n if (!this._element.getAttribute('aria-label') && !this._element.textContent.trim()) {\n this._element.setAttribute('aria-label', title)\n }\n\n this._element.setAttribute('data-bs-original-title', title) // DO NOT USE IT. Is only for backwards compatibility\n this._element.removeAttribute('title')\n }\n\n _enter() {\n if (this._isShown() || this._isHovered) {\n this._isHovered = true\n return\n }\n\n this._isHovered = true\n\n this._setTimeout(() => {\n if (this._isHovered) {\n this.show()\n }\n }, this._config.delay.show)\n }\n\n _leave() {\n if (this._isWithActiveTrigger()) {\n return\n }\n\n this._isHovered = false\n\n this._setTimeout(() => {\n if (!this._isHovered) {\n this.hide()\n }\n }, this._config.delay.hide)\n }\n\n _setTimeout(handler, timeout) {\n clearTimeout(this._timeout)\n this._timeout = setTimeout(handler, timeout)\n }\n\n _isWithActiveTrigger() {\n return Object.values(this._activeTrigger).includes(true)\n }\n\n _getConfig(config) {\n const dataAttributes = Manipulator.getDataAttributes(this._element)\n\n for (const dataAttribute of Object.keys(dataAttributes)) {\n if (DISALLOWED_ATTRIBUTES.has(dataAttribute)) {\n delete dataAttributes[dataAttribute]\n }\n }\n\n config = {\n ...dataAttributes,\n ...(typeof config === 'object' && config ? config : {})\n }\n config = this._mergeConfigObj(config)\n config = this._configAfterMerge(config)\n this._typeCheckConfig(config)\n return config\n }\n\n _configAfterMerge(config) {\n config.container = config.container === false ? document.body : getElement(config.container)\n\n if (typeof config.delay === 'number') {\n config.delay = {\n show: config.delay,\n hide: config.delay\n }\n }\n\n if (typeof config.title === 'number') {\n config.title = config.title.toString()\n }\n\n if (typeof config.content === 'number') {\n config.content = config.content.toString()\n }\n\n return config\n }\n\n _getDelegateConfig() {\n const config = {}\n\n for (const [key, value] of Object.entries(this._config)) {\n if (this.constructor.Default[key] !== value) {\n config[key] = value\n }\n }\n\n config.selector = false\n config.trigger = 'manual'\n\n // In the future can be replaced with:\n // const keysWithDifferentValues = Object.entries(this._config).filter(entry => this.constructor.Default[entry[0]] !== this._config[entry[0]])\n // `Object.fromEntries(keysWithDifferentValues)`\n return config\n }\n\n _disposePopper() {\n if (this._popper) {\n this._popper.destroy()\n this._popper = null\n }\n\n if (this.tip) {\n this.tip.remove()\n this.tip = null\n }\n }\n\n // Static\n static jQueryInterface(config) {\n return this.each(function () {\n const data = Tooltip.getOrCreateInstance(this, config)\n\n if (typeof config !== 'string') {\n return\n }\n\n if (typeof data[config] === 'undefined') {\n throw new TypeError(`No method named \"${config}\"`)\n }\n\n data[config]()\n })\n }\n}\n\n/**\n * jQuery\n */\n\ndefineJQueryPlugin(Tooltip)\n\nexport default Tooltip\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap popover.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport Tooltip from './tooltip.js'\nimport { defineJQueryPlugin } from './util/index.js'\n\n/**\n * Constants\n */\n\nconst NAME = 'popover'\n\nconst SELECTOR_TITLE = '.popover-header'\nconst SELECTOR_CONTENT = '.popover-body'\n\nconst Default = {\n ...Tooltip.Default,\n content: '',\n offset: [0, 8],\n placement: 'right',\n template: '
' +\n '
' +\n '

' +\n '
' +\n '
',\n trigger: 'click'\n}\n\nconst DefaultType = {\n ...Tooltip.DefaultType,\n content: '(null|string|element|function)'\n}\n\n/**\n * Class definition\n */\n\nclass Popover extends Tooltip {\n // Getters\n static get Default() {\n return Default\n }\n\n static get DefaultType() {\n return DefaultType\n }\n\n static get NAME() {\n return NAME\n }\n\n // Overrides\n _isWithContent() {\n return this._getTitle() || this._getContent()\n }\n\n // Private\n _getContentForTemplate() {\n return {\n [SELECTOR_TITLE]: this._getTitle(),\n [SELECTOR_CONTENT]: this._getContent()\n }\n }\n\n _getContent() {\n return this._resolvePossibleFunction(this._config.content)\n }\n\n // Static\n static jQueryInterface(config) {\n return this.each(function () {\n const data = Popover.getOrCreateInstance(this, config)\n\n if (typeof config !== 'string') {\n return\n }\n\n if (typeof data[config] === 'undefined') {\n throw new TypeError(`No method named \"${config}\"`)\n }\n\n data[config]()\n })\n }\n}\n\n/**\n * jQuery\n */\n\ndefineJQueryPlugin(Popover)\n\nexport default Popover\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap scrollspy.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport BaseComponent from './base-component.js'\nimport EventHandler from './dom/event-handler.js'\nimport SelectorEngine from './dom/selector-engine.js'\nimport { defineJQueryPlugin, getElement, isDisabled, isVisible } from './util/index.js'\n\n/**\n * Constants\n */\n\nconst NAME = 'scrollspy'\nconst DATA_KEY = 'bs.scrollspy'\nconst EVENT_KEY = `.${DATA_KEY}`\nconst DATA_API_KEY = '.data-api'\n\nconst EVENT_ACTIVATE = `activate${EVENT_KEY}`\nconst EVENT_CLICK = `click${EVENT_KEY}`\nconst EVENT_LOAD_DATA_API = `load${EVENT_KEY}${DATA_API_KEY}`\n\nconst CLASS_NAME_DROPDOWN_ITEM = 'dropdown-item'\nconst CLASS_NAME_ACTIVE = 'active'\n\nconst SELECTOR_DATA_SPY = '[data-bs-spy=\"scroll\"]'\nconst SELECTOR_TARGET_LINKS = '[href]'\nconst SELECTOR_NAV_LIST_GROUP = '.nav, .list-group'\nconst SELECTOR_NAV_LINKS = '.nav-link'\nconst SELECTOR_NAV_ITEMS = '.nav-item'\nconst SELECTOR_LIST_ITEMS = '.list-group-item'\nconst SELECTOR_LINK_ITEMS = `${SELECTOR_NAV_LINKS}, ${SELECTOR_NAV_ITEMS} > ${SELECTOR_NAV_LINKS}, ${SELECTOR_LIST_ITEMS}`\nconst SELECTOR_DROPDOWN = '.dropdown'\nconst SELECTOR_DROPDOWN_TOGGLE = '.dropdown-toggle'\n\nconst Default = {\n offset: null, // TODO: v6 @deprecated, keep it for backwards compatibility reasons\n rootMargin: '0px 0px -25%',\n smoothScroll: false,\n target: null,\n threshold: [0.1, 0.5, 1]\n}\n\nconst DefaultType = {\n offset: '(number|null)', // TODO v6 @deprecated, keep it for backwards compatibility reasons\n rootMargin: 'string',\n smoothScroll: 'boolean',\n target: 'element',\n threshold: 'array'\n}\n\n/**\n * Class definition\n */\n\nclass ScrollSpy extends BaseComponent {\n constructor(element, config) {\n super(element, config)\n\n // this._element is the observablesContainer and config.target the menu links wrapper\n this._targetLinks = new Map()\n this._observableSections = new Map()\n this._rootElement = getComputedStyle(this._element).overflowY === 'visible' ? null : this._element\n this._activeTarget = null\n this._observer = null\n this._previousScrollData = {\n visibleEntryTop: 0,\n parentScrollTop: 0\n }\n this.refresh() // initialize\n }\n\n // Getters\n static get Default() {\n return Default\n }\n\n static get DefaultType() {\n return DefaultType\n }\n\n static get NAME() {\n return NAME\n }\n\n // Public\n refresh() {\n this._initializeTargetsAndObservables()\n this._maybeEnableSmoothScroll()\n\n if (this._observer) {\n this._observer.disconnect()\n } else {\n this._observer = this._getNewObserver()\n }\n\n for (const section of this._observableSections.values()) {\n this._observer.observe(section)\n }\n }\n\n dispose() {\n this._observer.disconnect()\n super.dispose()\n }\n\n // Private\n _configAfterMerge(config) {\n // TODO: on v6 target should be given explicitly & remove the {target: 'ss-target'} case\n config.target = getElement(config.target) || document.body\n\n // TODO: v6 Only for backwards compatibility reasons. Use rootMargin only\n config.rootMargin = config.offset ? `${config.offset}px 0px -30%` : config.rootMargin\n\n if (typeof config.threshold === 'string') {\n config.threshold = config.threshold.split(',').map(value => Number.parseFloat(value))\n }\n\n return config\n }\n\n _maybeEnableSmoothScroll() {\n if (!this._config.smoothScroll) {\n return\n }\n\n // unregister any previous listeners\n EventHandler.off(this._config.target, EVENT_CLICK)\n\n EventHandler.on(this._config.target, EVENT_CLICK, SELECTOR_TARGET_LINKS, event => {\n const observableSection = this._observableSections.get(event.target.hash)\n if (observableSection) {\n event.preventDefault()\n const root = this._rootElement || window\n const height = observableSection.offsetTop - this._element.offsetTop\n if (root.scrollTo) {\n root.scrollTo({ top: height, behavior: 'smooth' })\n return\n }\n\n // Chrome 60 doesn't support `scrollTo`\n root.scrollTop = height\n }\n })\n }\n\n _getNewObserver() {\n const options = {\n root: this._rootElement,\n threshold: this._config.threshold,\n rootMargin: this._config.rootMargin\n }\n\n return new IntersectionObserver(entries => this._observerCallback(entries), options)\n }\n\n // The logic of selection\n _observerCallback(entries) {\n const targetElement = entry => this._targetLinks.get(`#${entry.target.id}`)\n const activate = entry => {\n this._previousScrollData.visibleEntryTop = entry.target.offsetTop\n this._process(targetElement(entry))\n }\n\n const parentScrollTop = (this._rootElement || document.documentElement).scrollTop\n const userScrollsDown = parentScrollTop >= this._previousScrollData.parentScrollTop\n this._previousScrollData.parentScrollTop = parentScrollTop\n\n for (const entry of entries) {\n if (!entry.isIntersecting) {\n this._activeTarget = null\n this._clearActiveClass(targetElement(entry))\n\n continue\n }\n\n const entryIsLowerThanPrevious = entry.target.offsetTop >= this._previousScrollData.visibleEntryTop\n // if we are scrolling down, pick the bigger offsetTop\n if (userScrollsDown && entryIsLowerThanPrevious) {\n activate(entry)\n // if parent isn't scrolled, let's keep the first visible item, breaking the iteration\n if (!parentScrollTop) {\n return\n }\n\n continue\n }\n\n // if we are scrolling up, pick the smallest offsetTop\n if (!userScrollsDown && !entryIsLowerThanPrevious) {\n activate(entry)\n }\n }\n }\n\n _initializeTargetsAndObservables() {\n this._targetLinks = new Map()\n this._observableSections = new Map()\n\n const targetLinks = SelectorEngine.find(SELECTOR_TARGET_LINKS, this._config.target)\n\n for (const anchor of targetLinks) {\n // ensure that the anchor has an id and is not disabled\n if (!anchor.hash || isDisabled(anchor)) {\n continue\n }\n\n const observableSection = SelectorEngine.findOne(decodeURI(anchor.hash), this._element)\n\n // ensure that the observableSection exists & is visible\n if (isVisible(observableSection)) {\n this._targetLinks.set(decodeURI(anchor.hash), anchor)\n this._observableSections.set(anchor.hash, observableSection)\n }\n }\n }\n\n _process(target) {\n if (this._activeTarget === target) {\n return\n }\n\n this._clearActiveClass(this._config.target)\n this._activeTarget = target\n target.classList.add(CLASS_NAME_ACTIVE)\n this._activateParents(target)\n\n EventHandler.trigger(this._element, EVENT_ACTIVATE, { relatedTarget: target })\n }\n\n _activateParents(target) {\n // Activate dropdown parents\n if (target.classList.contains(CLASS_NAME_DROPDOWN_ITEM)) {\n SelectorEngine.findOne(SELECTOR_DROPDOWN_TOGGLE, target.closest(SELECTOR_DROPDOWN))\n .classList.add(CLASS_NAME_ACTIVE)\n return\n }\n\n for (const listGroup of SelectorEngine.parents(target, SELECTOR_NAV_LIST_GROUP)) {\n // Set triggered links parents as active\n // With both
    and