1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983
|
libspectrum 1.5.0
=================
libspectrum is a fairly simple library designed to make the handling
of various ZX Spectrum emulator-related file formats easy. So far it
handles:
* Snapshots: .z80, .szx, .sna (all read/write), .zxs, .sp., .snp and
+D snapshots (read only).
* Tape images: .tzx, .tap, .spc, .sta and .ltp (read/write) and
.pzx, Warajevo .tap, Z80Em and CSW version 1 (read only).
* Input recordings: .rzx (read/write).
* Disk images: .dsk (both plain and extended), .d40, .d80, .fdi, .img, .mgt,
.opd, .sad, .scl, .td0, .trd and .udi (identification only).
* Timex cartridges: .dck (read only).
* IDE hard disk images: .hdf (read/write).
* Microdrive cartridge images: .mdr (read/write).
There are also some subsidiary functions which may be generally useful
for Spectrum-related utilities.
General conventions
===================
Naming conventions:
*_alloc: give us a new object
*_free: we're done with this object
*_read: restore object from serialised form
*_write: serialise object
Calling conventions:
* In general, all output parameters (those which may be changed by
the function) should be before all input parameters
Library capabilities
====================
If the library supports zlib compression (as is used, for instance in
SZX snapshots), then then the constant
LIBSPECTRUM_SUPPORTS_ZLIB_COMPRESSION will be defined and non-zero. If
the library does not support zlib compression, then the constant will
not be defined.
Bzip2 compression is similarly covered by LIBSPECTRUM_SUPPORTS_BZ2_COMPRESSION
and WAV file support is covered by LIBSPECTRUM_SUPPORTS_AUDIOFILE.
Defined types
=============
libspectrum defines eight standard types which may be of use:
libspectrum_byte An unsigned 8-bit integer
libspectrum_signed_byte A signed 8-bit integer
libspectrum_word An unsigned 16-bit integer
libspectrum_signed_word A signed 16-bit integer
libspectrum_dword An unsigned 32-bit integer
libspectrum_signed_dword A signed 32-bit integer
libspectrum_qword An unsigned 64-bit integer
libspectrum_signed_qword A signed 64-bit integer
Initialisation etc
==================
libspectrum_error libspectrum_init( void )
This routine must be called before any other libspectrum routines,
other than `libspectrum_version', `libspectrum_check_version' and
`libspectrum_mem_set_vtable' to initialise the library. If it isn't
called, undefined behaviour may result.
const char *libspectrum_version( void )
This routine returns the version of libspectrum in use, in a "x.y.z.a"
format.
const char *libspectrum_gcrypt_version( void )
This routine returns the version of libgcrypt being used by
libspectrum, or NULL if an appropriate version of libgcrypt is not
available.
int libspectrum_check_version( const char *version )
This routine checks whether the version of libspectrum is at least
`version', which should be specified in an "x.y.z.a" format. It
returns non-zero if the libspectrum version in use is at least
`version' or zero if it is not.
Memory handling
===============
By default, libspectrum will use the standard library's malloc(),
calloc(), realloc() and free() for memory handling, but wrapped so that
they are "strong" (they will either succeed or abort the program). It is
possible to replace these with custom allocation routines if you wish.
typedef void* (*libspectrum_malloc_fn_t)( size_t size );
typedef void* (*libspectrum_calloc_fn_t)( size_t nmemb, size_t size );
typedef void* (*libspectrum_realloc_fn_t)( void *ptr, size_t size );
typedef void (*libspectrum_free_fn_t)( void *ptr );
typedef struct libspectrum_mem_vtable_t {
libspectrum_malloc_fn_t malloc;
libspectrum_calloc_fn_t calloc;
libspectrum_realloc_fn_t realloc;
libspectrum_free_fn_t free;
} libspectrum_mem_vtable_t;
void libspectrum_mem_set_vtable( libspectrum_mem_vtable_t *table )
Set the memory handling routines to be those specified by `table'. This
function may *not* be called after libspectrum_init() has been called.
Note that libspectrum will ensure that the memory allocators are still
strong, and will abort the program if any of the allocators returns
NULL.
Error handling
==============
All libspectrum functions signal errors in two ways: by returning an
non-zero error code of type `libspectrum_error' and by calling
`libspectrum_error_function'. The `libspectrum_error' enum can take the
following values:
LIBSPECTRUM_ERROR_NONE No error; guaranteed to have value 0
LIBSPECTRUM_ERROR_WARNING A warning, rather than a real error
LIBSPECTRUM_ERROR_MEMORY Out of memory
LIBSPECTRUM_ERROR_UNKNOWN Data not recognised
LIBSPECTRUM_ERROR_CORRUPT Invalid data
LIBSPECTRUM_ERROR_SIGNATURE File does not have the right signature
LIBSPECTRUM_ERROR_SLT Ugly kludge used to indicate that a .z80
file contains .slt data
LIBSPECTRUM_ERROR_INVALID An invalid parameter was supplied to a
function
LIBSPECTRUM_ERROR_LOGIC An internal logic error has occurred;
should never be seen
`libspectrum_error_function' is an object of type
`libspectrum_error_function_t':
libspectrum_error (*libspectrum_error_function_t)(
libspectrum_error error, const char *format, va_list ap
)
On error, `libspectrum_error_function' will be called, with `error'
being one of the standard codes, and `format' and `ap' are the standard
arguments suitable for passing to one of the v*printf functions to
create a text message giving more details on the error. If
`libspectrum_error_function' is not set by the user code,
`libspectrum_default_error_function' will be used: this simply outputs
the message to stderr, prefixed with "libspectrum error: " and ending
with a newline. (Additionally, it will call abort() if the error was of
type LIBSPECTRUM_ERROR_LOGIC, but that shouldn't happen...)
General functions
=================
Functions which don't relate directly to one file type or another.
Machine types and capabilities
------------------------------
In some places (notably in the `libspectrum_snap' structure),
libspectrum needs to identify the Spectrum variant in use. This is done
with the `libspectrum_machine' enum, which can take the following
values:
LIBSPECTRUM_MACHINE_16 16K Spectrum
LIBSPECTRUM_MACHINE_48 48K Spectrum
LIBSPECTRUM_MACHINE_48_NTSC NTSC version of 48K Spectrum
LIBSPECTRUM_MACHINE_128 (Original) 128K Spectrum
LIBSPECTRUM_MACHINE_128E Spectrum 128Ke
LIBSPECTRUM_MACHINE_PLUS2 Spectrum +2 (the grey one)
LIBSPECTRUM_MACHINE_PLUS2A Spectrum +2A (the black one)
LIBSPECTRUM_MACHINE_PLUS3 Spectrum +3
LIBSPECTRUM_MACHINE_PLUS3E Spectrum +3e
LIBSPECTRUM_MACHINE_TC2048 Timex TC2048
LIBSPECTRUM_MACHINE_TC2068 Timex TC2068
LIBSPECTRUM_MACHINE_TS2068 Timex TS2068
LIBSPECTRUM_MACHINE_PENT Pentagon 128
LIBSPECTRUM_MACHINE_PENT512 Pentagon 512
LIBSPECTRUM_MACHINE_PENT1024 Pentagon 1024
LIBSPECTRUM_MACHINE_SCORP Scorpion ZS 256
LIBSPECTRUM_MACHINE_SE Spectrum SE
The `libspectrum_machine_name' function:
const char* libspectrum_machine_name( libspectrum_machine type )
will return a text string giving the name of the machine (or "unknown"
if it doesn't recognise the type). This string is statically allocated
and so should not be modified by user code in any way.
The `libspectrum_machine_capabilities' function:
int libspectrum_machine_capabilities( libspectrum_machine type )
will tell you which features (above and beyond those found on the base
48K machine) a given `libspectrum_machine' has. It returns a bitwise OR
of the following constants:
LIBSPECTRUM_MACHINE_CAPABILITY_128_MEMORY
This machine has 128K of memory accessible as on the 128K machine.
LIBSPECTRUM_MACHINE_CAPABILITY_AY
This machine has an AY-3-8912 sound chip (as in the 128K and later
machines).
LIBSPECTRUM_MACHINE_CAPABILITY_EVEN_M1
Processor M1 cycles on this machine always start on even tstate
counts.
LIBSPECTRUM_MACHINE_CAPABILITY_KEMPSTON_JOYSTICK
This machine has built-in Kempston joystick ports as on the TC2048.
LIBSPECTRUM_MACHINE_CAPABILITY_NTSC
This machine has an NTSC video output.
LIBSPECTRUM_MACHINE_CAPABILITY_PENT1024_MEMORY
This machine has 1024K of memory accessible as on the Pentagon 1024.
LIBSPECTRUM_MACHINE_CAPABILITY_PENT512_MEMORY
This machine has 512K of memory accessible as on the Pentagon 512.
LIBSPECTRUM_MACHINE_CAPABILITY_PLUS3_MEMORY
This machine can change into all-RAM configurations as the +2A/+3.
LIBSPECTRUM_MACHINE_CAPABILITY_PLUS3_DISK
This machine has a disk drive similar to that on the +3.
LIBSPECTRUM_MACHINE_CAPABILITY_SCORP_MEMORY
This machine has memory paging capabilities like those found on the
Scorpion ZS 256.
LIBSPECTRUM_MACHINE_CAPABILITY_SE_MEMORY
This machine has memory paging capabilities like those found on the
Spectrum SE.
LIBSPECTRUM_MACHINE_CAPABILITY_SINCLAIR_JOYSTICK
This machine has built-in Sinclair joystick ports as on the +2/+2A/+3.
LIBSPECTRUM_MACHINE_CAPABILITY_TIMEX_DOCK
This machine has a `dock' (cartridge port) similar to that found on
the TC2068.
LIBSPECTRUM_MACHINE_CAPABILITY_TIMEX_MEMORY
This machine has memory paging capabilities similar to that of the
TC2048 and TC2068.
LIBSPECTRUM_MACHINE_CAPABILITY_TIMEX_VIDEO
This machine has additional video modes as found on the TC2048 and
TC2068.
LIBSPECTRUM_MACHINE_CAPABILITY_TRDOS_DISK
This machine has a disk drive similar to a TR-DOS device
File identification
-------------------
The `libspectrum_identify_file_raw' function will, if given a file's
contents and optionally its filename, will make a `best guess' as to
what sort of file it is:
libspectrum_error
libspectrum_identify_file_raw( libspectrum_id_t *type, const char *filename,
const unsigned char *buffer, size_t length )
`filename' should be the name of the file to be identified, or NULL if
it is unknown. `buffer' and `length' are the contents and length of the
file respectively.
The type of file will be returned in the `type' parameter, and can take
the following values:
LIBSPECTRUM_ID_UNKNOWN Couldn't identify this file
LIBSPECTRUM_ID_AUX_POK A .pok poke file
LIBSPECTRUM_ID_CARTRIDGE_DCK A .dck Timex dock image
LIBSPECTRUM_ID_CARTRIDGE_IF2 A .rom Interface 2 cartridge
LIBSPECTRUM_ID_COMPRESSED_BZ2 A bzip2 compressed file
LIBSPECTRUM_ID_COMPRESSED_GZ A gzip compressed file
LIBSPECTRUM_ID_COMPRESSED_ZIP A zip compressed file
LIBSPECTRUM_ID_DISK_D80 A .d80 or .d40 Didaktik 80/40 disk file
LIBSPECTRUM_ID_DISK_DSK A .dsk +3 disk file
LIBSPECTRUM_ID_DISK_CPC A plain .dsk +3 disk file
LIBSPECTRUM_ID_DISK_ECPC An extended .dsk +3 disk file
LIBSPECTRUM_ID_DISK_FDI A .fdi generic disk file
LIBSPECTRUM_ID_DISK_IMG A .img DISCiPLE/+D disk file
LIBSPECTRUM_ID_DISK_MGT A .mgt DISCiPLE/+D disk file
LIBSPECTRUM_ID_DISK_OPD A .opd or .opu Opus Discovery disk file
LIBSPECTRUM_ID_DISK_SAD A .sad generic disk file
LIBSPECTRUM_ID_DISK_SCL A .scl TRDOS disk file
LIBSPECTRUM_ID_DISK_TRD A .trd TRDOS disk file
LIBSPECTRUM_ID_DISK_TD0 A .td0 generic disk file
LIBSPECTRUM_ID_DISK_UDI A .udi generic disk file
LIBSPECTRUM_ID_HARDDISK_HDF A .hdf IDE hard disk image
LIBSPECTRUM_ID_MICRODRIVE_MDR A .mdf microdrive cartridge
LIBSPECTRUM_ID_RECORDING_RZX A .rzx input recording
LIBSPECTRUM_ID_SNAPSHOT_PLUSD A +D snapshot
LIBSPECTRUM_ID_SNAPSHOT_SNA A .sna snapshot
LIBSPECTRUM_ID_SNAPSHOT_SNP A .snp snapshot
LIBSPECTRUM_ID_SNAPSHOT_SP A .sp snapshot
LIBSPECTRUM_ID_SNAPSHOT_SZX A .szx snapshot (as used by Spectaculator)
LIBSPECTRUM_ID_SNAPSHOT_Z80 A .z80 snapshot
LIBSPECTRUM_ID_SNAPSHOT_ZXS A .zxs snapshot (as used by zx32)
LIBSPECTRUM_ID_TAPE_CSW A .csw tape image
LIBSPECTRUM_ID_TAPE_TAP A `normal' (Z80-style) .tap tape image
LIBSPECTRUM_ID_TAPE_TZX A .tzx tape image
LIBSPECTRUM_ID_TAPE_WARAJEVO A Warajevo-style .tap tape image
LIBSPECTRUM_ID_TAPE_Z80EM A Z80Em tape image
LIBSPECTRUM_ID_TAPE_SPC An SP-style .spc tape image
LIBSPECTRUM_ID_TAPE_STA A Speculator-style .sta tape image
LIBSPECTRUM_ID_TAPE_LTP A Nuclear ZX-style .ltp tape image
LIBSPECTRUM_ID_TAPE_PZX A .pzx tape image
Versions of libspectrum previous to 0.5.0 used LIBSPECTRUM_ID_DISK_DSK
for both plain and extended .dsk images, but this is now deprecated in
favour of the more specific LIBSPECTRUM_ID_DISK_CPC and
LIBSPECTRUM_ID_DISK_ECPC.
`libspectrum_identify_file_raw' looks for defined signatures in the
file as well as the extension of the filename and a couple of
heuristics in its attempts to identify the file. It's not perfect
(especially when given files with the wrong extension), but it should
work in most cases.
When dealing with compressed files, you are probably interested in the
data after it has been decompressed rather the original file. This can
be accomplished with the `libspectrum_identify_file' function:
libspectrum_error
libspectrum_identify_file( libspectrum_id_t *type, const char *filename,
const unsigned char *buffer, size_t length )
The parameters are the same as for `libspectrum_identify_file_raw'.
What in many cases may be more useful than the specific type of the
file is whether the file is a snapshot, a tape image or whatever. This
can be done with the `libspectrum_identify_class' function:
libspectrum_error libspectrum_identify_class( libspectrum_class_t *class,
libspectrum_id_t type )
which returns the type of file represented by the `type' parameter in
`*class'. The available values are:
LIBSPECTRUM_CLASS_UNKNOWN An unknown file type
LIBSPECTRUM_CLASS_AUXILIARY An auxiliary file
LIBSPECTRUM_CLASS_CARTRIDGE_TIMEX A Timex dock cartridge
LIBSPECTRUM_CLASS_CARTRIDGE_IF2 An Interface 2 cartridge
LIBSPECTRUM_CLASS_DISK_DIDAKTIK A Didaktik 80/40 disk image
LIBSPECTRUM_CLASS_DISK_GENERIC A generic disk image
LIBSPECTRUM_CLASS_DISK_OPUS An Opus Discovery disk image
LIBSPECTRUM_CLASS_DISK_PLUSD A DISCiPLE/+D disk image
LIBSPECTRUM_CLASS_DISK_PLUS3 A +3 disk image
LIBSPECTRUM_CLASS_DISK_TRDOS A TRDOS disk image
LIBSPECTRUM_CLASS_HARDDISK An IDE hard disk image
LIBSPECTRUM_CLASS_MICRODRIVE A microdrive cartridge
LIBSPECTRUM_CLASS_RECORDING An input recording
LIBSPECTRUM_CLASS_SNAPSHOT A snapshot
LIBSPECTRUM_CLASS_TAPE A tape image
One final routine, `libspectrum_identify_file_with_class',
libspectrum_error
libspectrum_identify_file_with_class(
libspectrum_id_t *type, libspectrum_class_t *libspectrum_class,
const char *filename, const unsigned char *buffer, size_t length )
simply combines the calls to `libspectrum_identify_file' and
`libspectrum_identify_class', returning the file type in `*type' and
the file class in `*class'.
Machine timings
---------------
The `libspectrum_machine_timings_*' functions give information about
the speed and various timings constants used by the machines. Some of
these timings are almost certainly wrong; if you have any corrections,
please send them in. Each of the functions takes one of the
LIBSPECTRUM_MACHINE_* constants listed above and returns a timing for
that machine.
libspectrum_dword
libspectrum_timings_processor_speed( libspectrum_machine machine )
libspectrum_dword
libspectrum_timings_ay_speed( libspectrum_machine machine )
The speed in Hz of the main processor and of the AY clock.
libspectrum_word
libspectrum_timings_left_border( libspectrum_machine machine )
libspectrum_word
libspectrum_timings_horizontal_screen( libspectrum_machine machine )
libspectrum_word
libspectrum_timings_right_border( libspectrum_machine machine )
libspectrum_word
libspectrum_timings_horizontal_retrace( libspectrum_machine machine )
The length in tstates of the different parts of one scanline.
libspectrum_word
libspectrum_timings_tstates_per_line( libspectrum_machine machine )
The sum of the previous four numbers.
libspectrum_word
libspectrum_timings_top_border( libspectrum_machine machine )
libspectrum_word
libspectrum_timings_vertical_screen( libspectrum_machine machine )
libspectrum_word
libspectrum_timings_bottom_border( libspectrum_machine machine )
libspectrum_word
libspectrum_timings_vertical_retrace( libspectrum_machine machine )
The number of scanlines in the different parts of the screen.
libspectrum_word
libspectrum_timings_lines_per_frame( libspectrum_machine machine )
The sum of the previous four numbers.
libspectrum_dword
libspectrum_timings_tstates_per_frame( libspectrum_machine machine )
tstates_per_line * lines_per_frame.
libspectrum_word
libspectrum_timings_top_left_pixel( libspectrum_machine machine )
How many tstates after interrupt is the top-left pixel of the screen
displayed.
libspectrum_word
libspectrum_timings_interrupt_length( libspectrum_machine machine )
How about t-states the machine holds /INT low for on a maskable
interrupt.
Creator information
-------------------
Some formats (.szx snapshots and .rzx input recordings) allow
utilities to store some information regarding the creator of the file.
libspectrum provides a `libspectrum_creator' structure to store this
information.
libspectrum_creator* libspectrum_creator_alloc( void )
Allocate a new `libspectrum_creator' structure.
libspectrum_error libspectrum_creator_free( libspectrum_creator *creator )
Free the memory used by a `libspectrum_creator' structure.
libspectrum_error
libspectrum_creator_set_program( libspectrum_creator *creator,
const char *program )
const libspectrum_byte*
libspectrum_creator_program( libspectrum_creator *creator )
Set and retrieve the name of the program which created this file.
libspectrum_error libspectrum_creator_set_major( libspectrum_creator *creator,
libspectrum_word major )
libspectrum_word
libspectrum_creator_major( libspectrum_creator *creator )
Set and retrieve the major version number of the program which created
this file.
libspectrum_error libspectrum_creator_set_minor( libspectrum_creator *creator,
libspectrum_word minor )
libspectrum_word
libspectrum_creator_minor( libspectrum_creator *creator )
Set and retrieve the minor version number of the program which created
this file.
libspectrum_error
libspectrum_creator_set_competition_code( libspectrum_creator *creator,
libspectrum_dword competition_code )
libspectrum_dword
libspectrum_creator_competition_code( libspectrum_creator *creator )
Set and retrieve the `competition code' of the program which created
this file. The competition code can be used for on-line tournaments to
determine that a certain file was made after a specific code was
released. If you don't understand the previous, you almost certainly
don't need to worry about it!
libspectrum_error
libspectrum_creator_set_custom( libspectrum_creator *creator,
libspectrum_byte *data, size_t length )
libspectrum_byte* libspectrum_creator_custom( libspectrum_creator *creator )
size_t libspectrum_creator_custom_length( libspectrum_creator *creator )
Set and retrieve the (arbitrary) custom data from the program which
created this file.
Snapshot functions
==================
Functions for dealing with snapshot files. These act on an opaque
`libspectrum_snap' structure, which can be accessed via the following
routines:
libspectrum_snap* libspectrum_snap_alloc( void )
Allocate a new libspectrum_snap structure.
libspectrum_error libspectrum_snap_free( libspectrum_snap *snap )
Release a structure allocated with `libspectrum_snap_alloc'.
There is a family of functions which can be used to retrieve and set
the properties of a snapshot. The `retrieve' functions have the form
<type> libspectrum_snap_<name>( libspectrum_snap *snap )
which retrieves the value of the property <name>, while the `set'
functions have the form
void libspectrum_snap_set_<name>( libspectrum_snap *snap, <type> new_value )
which sets the value of <name> to `new_value'. For array properties,
the retrieval function has the form
<type> libspectrum_snap_<name>( libspectrum_snap *snap, int idx )
which retrieves the <name>[`idx'] and the set function has the form
void libspectrum_snap_set_<name>( libspectrum_snap *snap,
int idx, <type> new_value )
which sets <name>[`idx'].
The available properties (along with their types) are:
* libspectrum_machine machine
* libspectrum_byte a
* libspectrum_byte f
* libspectrum_word bc
* libspectrum_word de
* libspectrum_word hl
* libspectrum_byte a_
* libspectrum_byte f_
* libspectrum_word bc_
* libspectrum_word de_
* libspectrum_word hl_
* libspectrum_word ix
* libspectrum_word iy
* libspectrum_byte i
* libspectrum_byte r
* libspectrum_word sp
* libspectrum_word pc
* libspectrum_word memptr
* libspectrum_byte iff1
* libspectrum_byte iff2
* libspectrum_byte im
* libspectrum_dword tstates
* int halted
* int last_instruction_ei
* int last_instruction_set_f
* libspectrum_byte out_ula
* libspectrum_byte out_128_memoryport
* libspectrum_byte out_plus3_memoryport
* libspectrum_byte out_ay_registerport
* libspectrum_byte ay_registers[16]
* libspectrum_byte out_scld_hsr
* libspectrum_byte out_scld_dec
* int interface1_active
* int interface1_paged
* int interface1_drive_count
* int interface1_custom_rom
* libspectrum_byte* interface1_rom[1]
* size_t interface1_rom_length[1]
* int beta_active
* int beta_paged
* int beta_autoboot
* int beta_drive_count
* int beta_custom_rom
* int beta_direction
* libspectrum_byte beta_system
* libspectrum_byte beta_track
* libspectrum_byte beta_sector
* libspectrum_byte beta_data
* libspectrum_byte beta_status
* libspectrum_byte* beta_rom[1]
* int plusd_active
* int plusd_paged
* int plusd_drive_count
* int plusd_custom_rom
* int plusd_direction
* libspectrum_byte plusd_control
* libspectrum_byte plusd_track
* libspectrum_byte plusd_sector
* libspectrum_byte plusd_data
* libspectrum_byte plusd_status
* libspectrum_byte* plusd_rom[1]
* libspectrum_byte* plusd_ram[1]
* int opus_active
* int opus_paged
* int opus_drive_count
* int opus_custom_rom
* int opus_direction
* libspectrum_byte opus_track
* libspectrum_byte opus_sector
* libspectrum_byte opus_data
* libspectrum_byte opus_status
* libspectrum_byte opus_data_reg_a
* libspectrum_byte opus_data_dir_a
* libspectrum_byte opus_control_a
* libspectrum_byte opus_data_reg_b
* libspectrum_byte opus_data_dir_b
* libspectrum_byte opus_control_b
* libspectrum_byte* opus_rom[1]
* libspectrum_byte* opus_ram[1]
* int custom_rom
* size_t custom_rom_pages
* libspectrum_byte* roms[1]
* size_t rom_length[1]
* libspectrum_byte* pages[8]
* libspectrum_byte* slt[256]
* size_t slt_length[256]
* libspectrum_byte* slt_screen
* int slt_screen_level
* int zxatasp_active
* int zxatasp_upload
* int zxatasp_writeprotect
* libspectrum_byte zxatasp_port_a
* libspectrum_byte zxatasp_port_b
* libspectrum_byte zxatasp_port_c
* libspectrum_byte zxatasp_control
* size_t zxatasp_pages
* size_t zxatasp_current_page
* libspectrum_byte* zxatasp_ram[32]
* int zxcf_active
* int zxcf_upload
* libspectrum_byte zxcf_memctl
* size_t zxcf_pages
* libspectrum_byte* zxcf_ram[64]
* int interface2_active
* libspectrum_byte* interface2_rom[1]
* int dock_active
* libspectrum_byte exrom_ram[8]
* libspectrum_byte* exrom_cart[8]
* libspectrum_byte dock_ram[8]
* libspectrum_byte* dock_cart[8]
* int issue2
* size_t joystick_active_count
* libspectrum_joystick joystick_list[ SNAPSHOT_JOYSTICKS ]
* int joystick_inputs[ SNAPSHOT_JOYSTICKS ]
* int kempston_mouse_active
* int simpleide_active
* int divide_active
* int divide_eprom_writeprotect
* int divide_paged
* libspectrum_byte divide_control
* size_t divide_pages
* libspectrum_byte* divide_eprom[1]
* libspectrum_byte* divide_ram[4]
* int fuller_box_active
* int melodik_active
* int specdrum_active
* libspectrum_signed_byte specdrum_dac
* int spectranet_active
* int spectranet_paged
* int spectranet_paged_via_io
* int spectranet_nmi_flipflop
* int spectranet_programmable_trap_active
* int spectranet_programmable_trap_msb
* int spectranet_all_traps_disabled
* int spectranet_rst8_trap_disabled
* int spectranet_deny_downstream_a15
* int spectranet_page_a
* int spectranet_page_b
* libspectrum_word spectranet_programmable_trap
* libspectrum_byte* spectranet_w5100[1]
* libspectrum_byte* spectranet_flash[1]
* libspectrum_byte* spectranet_ram[1]
* int late_timings
* int zx_printer_active
* int usource_active
* int usource_paged
* int usource_custom_rom
* libspectrum_byte* usource_rom[1]
* size_t usource_rom_length[1]
* int disciple_active
* int disciple_paged
* int disciple_inhibit_button
* int disciple_drive_count
* int disciple_custom_rom
* int disciple_direction
* libspectrum_byte disciple_control
* libspectrum_byte disciple_track
* libspectrum_byte disciple_sector
* libspectrum_byte disciple_data
* libspectrum_byte disciple_status
* libspectrum_byte* disciple_rom[1]
* size_t disciple_rom_length[1]
* libspectrum_byte* disciple_ram[1]
* int didaktik80_active;
* int didaktik80_paged;
* int didaktik80_drive_count;
* int didaktik80_custom_rom;
* int didaktik80_direction;
* libspectrum_byte didaktik80_aux;
* libspectrum_byte didaktik80_track;
* libspectrum_byte didaktik80_sector;
* libspectrum_byte didaktik80_data;
* libspectrum_byte didaktik80_status;
* libspectrum_byte* didaktik80_rom[1];
* size_t didaktik80_rom_length[1];
* libspectrum_byte* didaktik80_ram[1];
* int covox_active
* libspectrum_byte covox_dac
* int multiface_active;
* int multiface_paged;
* int multiface_model_one;
* int multiface_model_128;
* int multiface_model_3;
* int multiface_disabled;
* int multiface_software_lockout;
* int multiface_red_button_disabled;
* libspectrum_byte* multiface_ram[1];
* size_t multiface_ram_length[1];
Most of those should be fairly self-explanatory; those which may not
be are:
* `a_', `f_', `bc_', `de_' and `hl_' functions represent the A', F',
BC', DE' and HL' registers.
* For 48K snaps, 0x4000 to 0x7fff is stored in `pages[5]', 0x8000 to
0xbfff in `pages[2]' and 0xc000 to 0xffff in `pages[0]' (This is
equivalent to the default mapping on the 128K machines).
* `last_instruction_ei' being non-zero signals that the opcode
previously executed was an EI and thus interrupts should not be
accepted at this point, but will be after the next opcode.
* `last_instruction_set_f' being non-zero signals that the opcode
previously executed affected the F register.
* `out_plus3_memoryport' should also be used to save the state of
the Scorpion's secondary memory control port (0x1ffd).
* `late_timings' being non-zero signals that the emulated Spectrum
should use timings 1 t-state later than usual as in some machines
that have warmed up.
* `zx_printer_active' being non-zero signals that the emulated Spectrum
has a ZX Printer connected.
* The `beta_*' functions represent the Betadisk
interface. `beta_paged' is non-zero if the Betadisk ROM is currently
paged in between 0x0000 and 0x3fff and `beta_direction' is non-zero
if the current seek direction is towards higher cylinders
(rimwards). The other `beta_*' functions represent the current
values of the Betadisk interface registers.
* The `zxatasp_*' and `zxcf_*' functions give the state of the ZXATASP
and ZXCF interfaces. `zxatasp_pages' and `zxcf_pages' give the
number of 16K RAM pages attached to the
interface. `zxatasp_current_page' gives the page which is currently
paged in via the ZXATASP, or 255 if no page is currently selected.
* `exrom_ram' and `dock_ram' are non-zero if the corresponding 8K page
of the Timex EXROM or DOCK are writable.
* The `spectranet_*' functions represent the Spectranet interface.
* `joystick_active_count' is the number of joysticks connected to the emulated
Spectrum. `joystick_list' gives the type of the joysticks and
`joystick_inputs' gives the corresponding connections to the real machines
keyboard and joysticks.
The available joystick types are defined by the libspectrum_joystick
enum, which can take the following values:
LIBSPECTRUM_JOYSTICK_NONE No joystick connected
LIBSPECTRUM_JOYSTICK_CURSOR Cursor joystick
LIBSPECTRUM_JOYSTICK_KEMPSTON Kempston joystick
LIBSPECTRUM_JOYSTICK_SINCLAIR_1 Sinclair joystick 1
LIBSPECTRUM_JOYSTICK_SINCLAIR_2 Sinclair joystick 2
LIBSPECTRUM_JOYSTICK_TIMEX_1 Timex joystick 1
LIBSPECTRUM_JOYSTICK_TIMEX_2 Timex joystick 2
LIBSPECTRUM_JOYSTICK_FULLER Fuller joystick
The joystick input values can be any of:
LIBSPECTRUM_JOYSTICK_INPUT_NONE Not connected
LIBSPECTRUM_JOYSTICK_INPUT_KEYBOARD Input from the real keyboard
LIBSPECTRUM_JOYSTICK_INPUT_JOYSTICK_1 Input from real joystick 1
LIBSPECTRUM_JOYSTICK_INPUT_JOYSTICK_2 Input from real joystick 2
With all those housekeeping routines out of the way, there are two
main workhorses of the snapshot routines:
libspectrum_error
libspectrum_snap_read( libspectrum_snap *snap, const libspectrum_byte *buffer,
size_t length, libspectrum_id_t type,
const char *filename )
Take the snapshot of type `type' of `length' bytes starting at
`buffer' and convert it to a `libspectrum_snap' structure. If `type'
is `LIBSPECTRUM_ID_UNKNOWN', guess the file format via
`libspectrum_identify_file'; `filename' is used only to help with the
identification process and can be set to NULL (or anything else) if
`type' is not `LIBSPECTRUM_ID_UNKNOWN'. Snapshots compressed with
bzip2 or gzip will be automatically and transparently decompressed.
libspectrum_error
libspectrum_snap_write( libspectrum_byte **buffer, size_t *length,
int *out_flags, libspectrum_snap *snap,
libspectrum_id_t type, libspectrum_creator *creator,
int in_flags )
Take the snapshot in `snap' and serialise it into `*buffer' as a
snapshot of `type'. On entry, '*buffer' is assumed to be allocated
'*length' bytes, and will grow if necessary; if '*length' is zero,
'*buffer' can be uninitialised on entry. `in_flags' can be used
specify minor changes to the snapshot; currently there are two
options:
LIBSPECTRUM_FLAG_SNAPSHOT_NO_COMPRESSION
This flag specifies that the snapshot should not be compressed for
formats where it would normally be (.z80 and .szx).
LIBSPECTRUM_FLAG_SNAPSHOT_ALWAYS_COMPRESS
This flag specifies that all the snapshot components should be
compressed for formats which would normally use some uncompressed
components when the file size would end up smaller. This is useful
for compatibility with programs that have problems with
uncompressed .z80 files, but also works with .szx snapshots.
`out_flags' will return the logical OR of some extra information from the
serialisation:
LIBSPECTRUM_FLAG_SNAPSHOT_MINOR_INFO_LOSS
A small amount of information was lost in serialisation. The
resultant snapshot may not work correctly.
LIBSPECTRUM_FLAG_SNAPSHOT_MAJOR_INFO_LOSS
A large amount of information was lost in serialisation. It is
highly likely that the resultant snapshot won't work.
`creator' gives the information which will be written into the
snapshot to specify the creator of the file. This can be NULL, in
which case no information will be written. Currently, only the .szx
format will make any use of this information.
The only formats for which serialisation is supported are .sna, .szx
and .z80.
Tape functions
==============
libspectrum uses the opaque `libspectrum_tape' structure to represent
a tape image. Essentially, a `libspectrum_tape' is a list of tape
blocks, which are of the `libspectrum_tape_block' type detailed below.
The routines for dealing with tapes are:
libspectrum_tape* libspectrum_tape_alloc( void )
Allocate a new libspectrum_tape object.
libspectrum_error libspectrum_tape_free( libspectrum_tape *tape )
Free the memory used by a libspectrum_tape objects;
libspectrum_error libspectrum_tape_clear( libspectrum_tape *tape )
Free the memory used by the blocks in a libspectrum_tape object, but
not the object itself; useful if you're about to read a new tape into
a current object.
libspectrum_error
libspectrum_tape_read( libspectrum_tape *tape, const libspectrum_byte *buffer,
size_t length, libspectrum_id_t type,
const char *filename )
Take the tape image of type `type' of `length' bytes starting at
`buffer' and convert it to a `libspectrum_tape' structure. If `type'
is `LIBSPECTRUM_ID_UNKNOWN', guess the file format via
`libspectrum_identify_file'; `filename' is generally used only to help
with the identification process and can be set to NULL (or anything
else) if `type' is not `LIBSPECTRUM_ID_UNKNOWN' unless the tape is a
WAV file where the underlying audiofile library will reread the
file and will not use the buffer. Tape images compressed with
bzip2 or gzip will be automatically and transparently decompressed.
libspectrum_error
libspectrum_tape_write( libspectrum_byte **buffer, size_t *length,
libspectrum_tape *tape, libspectrum_id_t type )
Take the snapshot in `tape and serialise it as a `type' format file
into `*buffer'. On entry, '*buffer' is assumed to be allocated
'*length' bytes, and will grow if necessary; if '*length' is zero,
'*buffer' can be uninitialised on entry.
libspectrum_error libspectrum_tape_get_next_edge( libspectrum_dword *tstates,
int *flags,
libspectrum_tape *tape )
This is the main workhorse function of the tape routines and will
return in `tstates' the number of tstates until the next edge should
occur from `tape'. `flags' will be set to the bitwise or of the
following:
LIBSPECTRUM_TAPE_FLAGS_BLOCK The current block ends with this edge
LIBSPECTRUM_TAPE_FLAGS_STOP User code should stop playing the tape
after this edge
LIBSPECTRUM_TAPE_FLAGS_STOP48 User code should stop playing the tape
after this edge if it was emulating a
48K machine. The desired behaviour for
things like the TC2048 is undefined in
the .tzx format :-(
LIBSPECTRUM_TAPE_FLAGS_LEVEL_LOW The input signal from the tape should be
forced low at this edge
LIBSPECTRUM_TAPE_FLAGS_LEVEL_HIGH The input signal from the tape should be
forced high at this edge
LIBSPECTRUM_TAPE_FLAGS_NO_EDGE This "edge" isn't really an edge and doesn't
change the input signal from the tape.
LIBSPECTRUM_TAPE_FLAGS_LENGTH_SHORT This edge is a "short" edge; used
for loader acceleration
LIBSPECTRUM_TAPE_FLAGS_LENGTH_LONG This edge is a "long" edge; again
used for loader acceleration
LIBSPECTRUM_TAPE_FLAGS_TAPE The current tape ends with this edge
int libspectrum_tape_present( libspectrum_tape *tape )
Returns non-zero if `tape' currently contains a tape image and zero
otherwise.
libspectrum_error libspectrum_tape_position( int *n, libspectrum_tape *tape )
Return in `n' the position of the current block on the tape. The first
block is block 0, the second block 1, etc.
libspectrum_error libspectrum_tape_nth_block( libspectrum_tape *tape, int n )
Set the current block on the tape to be the `n'th block and initialise
it. Again, the first block on the tape is block 0.
void
libspectrum_tape_append_block( libspectrum_tape *tape,
libspectrum_tape_block *block )
Append `block' to `tape'.
void
libspectrum_tape_remove_block( libspectrum_tape *tape,
libspectrum_tape_iterator it )
Remove the block pointed to by `it' (see the "Tape iterators" section)
from the tape.
libspectrum_error
libspectrum_tape_insert_block( libspectrum_tape *tape,
libspectrum_tape_block *block,
size_t position )
Insert `block' into `tape` in position `position', where position 0
would make the new block the first block on the tape.
libspectrum_tape_block*
libspectrum_tape_current_block( libspectrum_tape *tape )
Get the currently active block on the tape.
libspectrum_tape_block*
libspectrum_tape_peek_next_block( libspectrum_tape *tape )
Get the next block on the tape, but don't move the tape along or
initialise the block.
libspectrum_tape_block WIN32_DLL *
libspectrum_tape_peek_last_block( libspectrum_tape *tape )
Get the last block on the tape, but don't move the tape along or
initialise the block.
libspectrum_tape_block*
libspectrum_tape_select_next_block( libspectrum_tape *tape )
Move the tape along so it points to the next block, initialise that
block and return it.
Tape iterators
--------------
In some circumstances, a program may wish to look through all the
blocks in a tape, but not actually change the state of the tape at
all. This can be done with a `libspectrum_tape_iterator'.
There are two routines for dealing with iterators:
libspectrum_tape_block*
libspectrum_tape_iterator_init( libspectrum_tape_iterator *iterator,
libspectrum_tape *tape )
Initialise `iterator' to point to the first block of `tape' and return
that block. Returns NULL if the tape has no blocks.
libspectrum_tape_block*
libspectrum_tape_iterator_next( libspectrum_tape_iterator *iterator )
Make the already initialised `iterator' point to the next block of
`tape' and return that block (or NULL if there are no more blocks).
libspectrum_tape_block *
libspectrum_tape_iterator_peek_next( libspectrum_tape_iterator iterator )
Make the already initialised `iterator' return the next block of
`tape' (or NULL if there are no more blocks). The position of the `iterator'
is not modified.
Tape blocks
-----------
The block format used by libspectrum is very similar to that used by
the TZX format itself; see http://www.worldofspectrum.org/TZXformat.html
The block types supported by libspectrum (along with their block ID in
the TZX format) are the following:
LIBSPECTRUM_TAPE_BLOCK_ROM 0x10
LIBSPECTRUM_TAPE_BLOCK_TURBO 0x11
LIBSPECTRUM_TAPE_BLOCK_PURE_TONE 0x12
LIBSPECTRUM_TAPE_BLOCK_PULSES 0x13
LIBSPECTRUM_TAPE_BLOCK_PURE_DATA 0x14
LIBSPECTRUM_TAPE_BLOCK_RAW_DATA 0x15
LIBSPECTRUM_TAPE_BLOCK_GENERALISED_DATA 0x19
LIBSPECTRUM_TAPE_BLOCK_PAUSE 0x20
LIBSPECTRUM_TAPE_BLOCK_GROUP_START 0x21
LIBSPECTRUM_TAPE_BLOCK_GROUP_END 0x22
LIBSPECTRUM_TAPE_BLOCK_JUMP 0x23
LIBSPECTRUM_TAPE_BLOCK_LOOP_START 0x24
LIBSPECTRUM_TAPE_BLOCK_LOOP_END 0x25
LIBSPECTRUM_TAPE_BLOCK_SELECT 0x28
LIBSPECTRUM_TAPE_BLOCK_STOP48 0x2a
LIBSPECTRUM_TAPE_BLOCK_SET_SIGNAL_LEVEL 0x2b
LIBSPECTRUM_TAPE_BLOCK_COMMENT 0x30
LIBSPECTRUM_TAPE_BLOCK_MESSAGE 0x31
LIBSPECTRUM_TAPE_BLOCK_ARCHIVE_INFO 0x32
LIBSPECTRUM_TAPE_BLOCK_HARDWARE 0x33
LIBSPECTRUM_TAPE_BLOCK_CUSTOM 0x35
LIBSPECTRUM_TAPE_BLOCK_CONCAT 0x5a
The following blocks are not defined in the TZX format
LIBSPECTRUM_TAPE_BLOCK_RLE_PULSE A run-length encoded list of pulses
The following two blocks are defined in the PZX format
LIBSPECTRUM_TAPE_BLOCK_PULSE_SEQUENCE A run-length encoded list of pulses
with polarity specified
LIBSPECTRUM_TAPE_BLOCK_DATA_BLOCK A block of data without pilot or sync
pulses with bit encoding and polarity
specified
These values are defined in the `libspectrum_tape_type' enumeration.
The `concatenation' block (0x5a) is recognised on input, but just
skipped; hence it will never appear in a libspectrum_tape_block.
The basic routines for dealing with tape blocks are:
libspectrum_tape_block*
libspectrum_tape_block_alloc( libspectrum_tape_type type )
Allocate a new tape block of `type'.
libspectrum_error libspectrum_tape_block_free( libspectrum_tape_block *block )
Free a tape block.
libspectrum_tape_type
libspectrum_tape_block_type( libspectrum_tape_block *block )
Return the type of `block'.
libspectrum_error
libspectrum_tape_block_set_type( libspectrum_tape_block *block,
libspectrum_tape_type type )
Set the type of `block' to `type'.
libspectrum_error libspectrum_tape_block_init( libspectrum_tape_block *block )
Initialise `block' such that it is ready for playback (with
`libspectrum_tape_get_next_edge').
libspectrum_error
libspectrum_tape_block_description( char *buffer, size_t length,
libspectrum_tape_block *block )
Copy into `buffer' (which has been allocated at least `length' bytes by
the user code) a text description of the type of `block'.
Similar to the snapshot structure, there is a large family of routines
for setting and retrieving the parameters of individual block types.
For tape blocks, this becomes more complicated still as different
block types possess different parameters. If a `set' function is
called for a parameter which is not relevant to the current block
type, an error will be printed and LIBSPECTRUM_ERROR_INVALID returned.
For the `get' functions, an error will be printed and an undefined
value returned.
int
libspectrum_tape_block_metadata( libspectrum_tape_block *block )
Returns 1 if the block consists solely of metadata (comments, etc.) or
0 if it contains real data.
libspectrum_dword
libspectrum_tape_block_length( libspectrum_tape_block *block )
Returns the length (in tstates) of this block
The `get' and `set' functions follow the same pattern as for the
snapshot routines: the `get' functions are like
<type> libspectrum_tape_block_<name>( libspectrum_tape_block *block )
or
<type> libspectrum_tape_block_<name>( libspectrum_tape_block *block,
size_t index )
for array values and the `set' functions like
libspectrum_error
libspectrum_tape_block_set_<name>( libspectrum_tape_block *block,
<type> new_value )
or
libspectrum_error
libspectrum_tape_block_set_<name>( libspectrum_tape_block *block,
size_t index, <type> new_value )
The parameters, their types, and the LIBSPECTRUM_TAPE_BLOCK_* types
for which it is relevant are:
libspectrum_dword bit_length RAW_DATA
libspectrum_dword bit0_length PURE_DATA
TURBO
libspectrum_dword bit1_length PURE_DATA
TURBO
size_t bits_in_last_byte PURE_DATA
RAW_DATA
TURBO
DATA_BLOCK
size_t count PURE_TONE
PULSES
LOOP_START
SELECT
ARCHIVE_INFO
HARDWARE
PULSE_SEQUENCE
DATA_BLOCK
libspectrum_byte* data CUSTOM
PURE_DATA
RAW_DATA
ROM
TURBO
DATA_BLOCK
size_t data_length CUSTOM
PURE_DATA
RAW_DATA
ROM
TURBO
DATA_BLOCK
libspectrum_tape_generalised_data_symbol_table
data_table GENERALISED_DATA
int ids[] ARCHIVE_INFO
HARDWARE
int offset JUMP
int offsets[] SELECT
libspectrum_dword pause GENERALISED_DATA
MESSAGE
PAUSE
PURE_DATA
RAW_DATA
ROM
TURBO
libspectrum_dword pause_tstates GENERALISED_DATA
MESSAGE
PAUSE
PURE_DATA
RAW_DATA
ROM
TURBO
libspectrum_dword pilot_length TURBO
size_t pilot_pulses TURBO
libspectrum_word pilot_repeats GENERALISED_DATA
libspectrum_word pilot_symbols GENERALISED_DATA
libspectrum_tape_generalised_data_symbol_table
pilot_table GENERALISED_DATA
libspectrum_dword pulse_length LENGTH
libspectrum_dword pulse_lengths[] PULSES
PULSE_SEQUENCE
libspectrum_dword pulse_repeats[] PULSE_SEQUENCE
libspectrum_dword sync1_length TURBO
libspectrum_dword sync2_length TURBO
libspectrum_dword tail_length DATA_BLOCK
char* text GROUP_START
COMMENT
MESSAGE
CUSTOM
char* texts[] ARCHIVE_INFO
SELECT
int types[] HARDWARE
int values[] HARDWARE
int level DATA_BLOCK
PAUSE
SET_SIGNAL_LEVEL
libspectrum_byte bit0_pulse_count DATA_BLOCK
libspectrum_byte bit1_pulse_count DATA_BLOCK
libspectrum_word bit0_pulses[] DATA_BLOCK
libspectrum_word bit1_pulses[] DATA_BLOCK
There is one further parameter which can be accessed for PURE_DATA,
RAW_DATA, ROM and TURBO blocks, which is `libspectrum_tape_state_type
state'. This determines the part of the block which is currently being
played, and can have the following values:
LIBSPECTRUM_TAPE_STATE_INVALID /* Should never be seen */
LIBSPECTRUM_TAPE_STATE_PILOT /* Pilot pulses */
LIBSPECTRUM_TAPE_STATE_SYNC1 /* First sync pulse */
LIBSPECTRUM_TAPE_STATE_SYNC2 /* Second sync pulse */
LIBSPECTRUM_TAPE_STATE_DATA1 /* First edge of a data bit */
LIBSPECTRUM_TAPE_STATE_DATA2 /* Second edge of a data bit */
LIBSPECTRUM_TAPE_STATE_TAIL /* The tail pause following the last data bit */
LIBSPECTRUM_TAPE_STATE_PAUSE /* The pause at the end of a block */
Setting this value to anything other than
`LIBSPECTRUM_TAPE_STATE_PAUSE' will produce undefined results.
Exposing this parameter is an ugly hack needed by Fuse to allow for
flash-loading of tape blocks, and setting it should not be used unless
absolutely necessary.
The libspectrum_tape_generalised_data_symbol_table is an opaque data
structure which represents the "symbol table" used in the TZX
generalised data block (ID 0x19). It can be accessed with the
following routines:
libspectrum_dword
libspectrum_tape_generalised_data_symbol_table_symbols_in_block(
const libspectrum_tape_generalised_data_symbol_table *table )
libspectrum_byte
libspectrum_tape_generalised_data_symbol_table_max_pulses(
const libspectrum_tape_generalised_data_symbol_table *table )
libspectrum_word
libspectrum_tape_generalised_data_symbol_table_symbols_in_table
(const libspectrum_tape_generalised_data_symbol_table *table )
libspectrum_tape_generalised_data_symbol*
libspectrum_tape_generalised_data_symbol_table_symbol(
const libspectrum_tape_generalised_data_symbol_table *table, size_t which )
The libspectrum_tape_generalised_data_symbol represents one of the
symbols used in the generalised data block and can be accessed with
the following routines:
libspectrum_tape_generalised_data_symbol_edge_type
libspectrum_tape_generalised_data_symbol_type(
const libspectrum_tape_generalised_data_symbol *symbol )
libspectrum_word
libspectrum_tape_generalised_data_symbol_pulse(
const libspectrum_tape_generalised_data_symbol *symbol, size_t which )
The following edge types are available:
LIBSPECTRUM_TAPE_GENERALISED_DATA_SYMBOL_EDGE Invert signal polarity
LIBSPECTRUM_TAPE_GENERALISED_DATA_SYMBOL_NO_EDGE No polarity change
LIBSPECTRUM_TAPE_GENERALISED_DATA_SYMBOL_LOW Set signal low
LIBSPECTRUM_TAPE_GENERALISED_DATA_SYMBOL_HIGH Set signal high
Input recording functions
=========================
All input recording routines are accessed through the opaque
`libspectrum_rzx' structure.
libspectrum_rzx* libspectrum_rzx_alloc( void )
Allocate a new input recording object.
libspectrum_error libspectrum_rzx_free( libspectrum_rzx *rzx )
Free the memory used by an input recording object as allocated by
`libspectrum_rzx_alloc'.
void
libspectrum_rzx_start_input( libspectrum_rzx *rzx, libspectrum_dword tstates )
Start an input recording block in the object.
libspectrum_error libspectrum_rzx_stop_input( libspectrum_rzx *rzx )
Stop the current input recording block.
libspectrum_error
libspectrum_rzx_add_snap( libspectrum_rzx *rzx, libspectrum_snap *snap,
int automatic )
Add `snap' to the input recording at this point. `automatic' can be used
to indicate whether this block was automatically added by the calling
program (non-zero) or explicitly requested by the user (zero) and then
fetched with libspectrum_rzx_iterator_snap_is_automatic() (see below).
libspectrum_error
libspectrum_rzx_rollback( libspectrum_rzx *rzx, libspectrum_snap **snap )
Return the input recording to the state it was at which the last
snapshot was inserted. That state is set up in `snap'.
libspectrum_error
libspectrum_rzx_rollback_to( libspectrum_rzx *rzx, libspectrum_snap **snap,
size_t which )
Return the input recording to the state it was at which the <n>th
snapshot was inserted, where n is specified by `which'. That state is
set up in `snap'.
libspectrum_error libspectrum_rzx_store_frame( libspectrum_rzx *rzx,
size_t instructions,
size_t count,
libspectrum_byte *in_bytes )
Add a frame to `rzx' in which `instructions' opcodes where fetched,
and `count' bytes, specified in `in_bytes', were read from the IO
ports.
libspectrum_error libspectrum_rzx_start_playback( libspectrum_rzx *rzx )
Prepare to start playback of the input recording `rzx'.
libspectrum_error libspectrum_rzx_playback_frame( libspectrum_rzx *rzx,
int *finished,
libspectrum_snap **snap )
Move onto the next frame of playback from the input recording
`rzx'. If the last frame has now been played, `*finished' will be
non-zero, otherwise it will be zero. If a snap is present in the input
recording before the next frame, this will be returned in `*snap',
otherwise `*snap' will be NULL.
If the correct number of bytes were not read from `rzx' during the
frame via `libspectrum_rzx_playback', an error will be given.
libspectrum_error libspectrum_rzx_playback( libspectrum_rzx *rzx,
libspectrum_byte *byte )
Return in `*byte' the next byte to be read from the IO ports from the
current frame of `rzx'.
size_t libspectrum_rzx_tstates( libspectrum_rzx *rzx )
Return the 'starting tstates' field of `rzx'.
size_t libspectrum_rzx_set_tstates( libspectrum_rzx *rzx, size_t tstates )
Set (and return the new value of) the 'starting tstates' field of `rzx'.
size_t libspectrum_rzx_instructions( libspectrum_rzx *rzx )
Return the number of opcode fetches to be performed during the current
frame of `rzx'.
libspectrum_error
libspectrum_rzx_read( libspectrum_rzx *rzx, libspectrum_snap **snap,
const libspectrum_byte *buffer, const size_t length,
libspectrum_rzx_signature *signature )
Given a .rzx file of `length' bytes starting at `buffer', extract the
input recording data into `rzx' and the embedded snapshot into
`*snap'. If there is no embedded snapshot, `*snap' will be NULL after
the call. If the RZX file contains a digital signature, `*signature'
will contain the information from that signature; see below for
information on this. Files compressed with bzip2 or gzip will be
automatically and transparently decompressed.
libspectrum_error
libspectrum_rzx_write( libspectrum_byte **buffer, size_t *length,
libspectrum_rzx *rzx,
libspectrum_byte *snap, libspectrum_id_t snap_format,
libspectrum_creator *creator,
int compress, libspectrum_rzx_dsa_key *key )
Given input recording data in `rzx' and a snapshot in `snap', create a
.rzx file in `*buffer'. If no embedded snapshot is required, set
`snap' to be NULL. Before the call, `*buffer' should be allocated at
least `*length' bytes (can be zero). After the call, `*length'
contains the length of the .rzx file.
`snap format' specifies the format for the embedded snap. This can be
any of the formats supported by `libspectrum_snap_write' or
LIBSPECTRUM_ID_UNKNOWN, in which case the snap will be embedded as a
.z80 file, _unless_ that would result in major information loss, in
which case a .szx file will be embedded instead.
`creator' contains the creator information which should be written
into the RZX file. If `key' is non-NULL, the RZX file will be
digitally signed using the specified DSA key; see below for more
details.
void
libspectrum_rzx_insert_snap( libspectrum_rzx *rzx, libspectrum_snap *snap,
int where )
Insert `snap' into the RZX recording in position `where'. A `where' value of
zero is the first block in the file, before any current content.
void
libspectrum_rzx_iterator_delete( libspectrum_rzx *rzx,
libspectrum_rzx_iterator *it )
Delete the block pointed to by `it' from the RZX file `rzx'.
libspectrum_snap*
libspectrum_rzx_iterator_get_snap( libspectrum_rzx_iterator it )
Get the snapshot pointed to by `it'. If `it' does not point to a snapshot,
NULL is returned.
int
libspectrum_rzx_iterator_snap_is_automatic( libspectrum_rzx_iterator it )
Returns non-zero if `it' points to a snap which has its "automatic" flag
(see libspectrum_rzx_add_snap()) set to true, or false if it doesn't (or
if `it' doesn't point to a snapshot).
Input recording iterators
-------------------------
As with tapes, iterators are available to allow an application to
examine the structure of an input recording file.
Such an iterator is initialised via
libspectrum_rzx_iterator libspectrum_rzx_iterator_begin( libspectrum_rzx *rzx )
and moved to the next block via
libspectrum_rzx_iterator
libspectrum_rzx_iterator_next( libspectrum_rzx_iterator it )
The type of block pointed to by the iterator can be obtained via the
libspectrum_rzx_block_id
libspectrum_rzx_iterator_get_type( libspectrum_rzx_iterator it )
function. The return value will be one of:
LIBSPECTRUM_RZX_CREATOR_BLOCK Creator information
LIBSPECTRUM_RZX_SIGN_START_BLOCK Start of signed information
LIBSPECTRUM_RZX_SIGN_END_BLOCK End of signed information
LIBSPECTRUM_RZX_SNAPSHOT_BLOCK Snapshot
LIBSPECTRUM_RZX_INPUT_BLOCK Input recording block
If the iterator is pointing to a block of type LIBSPECTRUM_RZX_INPUT_BLOCK,
then the function
size_t libspectrum_rzx_iterator_get_frames( libspectrum_rzx_iterator it )
can be used to obtain the number of frames stored in the block.
Digital signatures in RZX files
-------------------------------
One use of input recording files is to allow a `best Spectrum games
player' tournament to be held: everybody records themselves playing a
game, sends in input recordings of themselves doing this, and then
everyone can see who is the best player. When using an emulator, it is
obviously rather easy to cheat at this by using snapshots, slowing
down the emulator and all sorts of other ways. Fundamentally, there's
no way round this problem except by running the emulator on trusted
hardware, which is a whole different kettle of fish.
One such `best player' tournament, the Speccy Tour 2003 (see
http://www.speccy.org/SpeccyTour03/ ) required that for an emulator to
be `allowable' for the Tour, it must implement a `competition mode' in
which snapshot saving etc is forbidden and must then `prove' that the
RZX file was made in competition mode by digitally signing the RZX
file. This is clearly still insecure as the key must be present in the
emulator to allow it to sign files, but that's what the organisers
wanted, so it's implemented in libspectrum. What information you wish
to draw from the presence or absence of a digital signature on an RZX
file is entirely up to you.
The digital signature routines use libgcrypt to provide the necessary
support. If this is not present when libspectrum is compiled, the
signature routines will not available.
If you're not aware of the DSA algorithm, the rest of this section
probably won't make much sense to you; go and read a good cryptography
textbook :-)
To sign an RZX file, all that is required is a DSA key. libspectrum
uses a `libspectrum_rzx_dsa_key' structure to represent this:
typedef struct libspectrum_rzx_dsa_key {
const char *p, *q, *g, *y, *x;
} libspectrum_rzx_dsa_key;
Each of the fields is one of the standard DSA parameters, stored as a
hex string with the MSB first. `x' should be set to NULL for a public
key.
When a digitally signed RZX file is read, the signature information
will be read into a `libspectrum_rzx_signature' structure:
typedef struct libspectrum_rzx_signature {
libspectrum_dword key_id;
const libspectrum_byte *start; ptrdiff_t length;
GcryMPI r, s;
} libspectrum_rzx_signature;
`key_id' is the low 32-bits of the `y' parameter of the key used to
sign this file; you'll have to implement your own lookup table to find
the rest of the key. `start' points to the signed data, which is
`length' bytes long. `r' and `s' are the standard DSA signature
parameters, stored in libgcrypt's native MPI format. (If libgcrypt is
not available, these parameters are simply not present in the
structure).
To verify a signature, simply call `libspectrum_verify_signature':
libspectrum_error
libspectrum_verify_signature( libspectrum_rzx_signature *signature,
libspectrum_rzx_dsa_key *key )
This will return LIBSPECTRUM_ERROR_NONE if the signature is valid or
LIBSPECTRUM_ERROR_SIGNATURE if it is invalid.
Once you're done with a signature, `libspectrum_signature_free' will
release the memory it was using:
libspectrum_error
libspectrum_signature_free( libspectrum_rzx_signature *signature )
Note this will not free the data pointed to by `start'.
Deprecated RZX function
-----------------------
libspectrum_error
libspectrum_rzx_write( libspectrum_byte **buffer, size_t *length,
libspectrum_rzx *rzx,
libspectrum_byte *snap, libspectrum_creator *creator,
int compress, libspectrum_rzx_dsa_key *key )
Exactly equivalent to libspectrum_rzx_write2( buffer, length, rzx,
snap, LIBSPECTRUM_ID_SNAPSHOT_Z80, creator, compress, key ).
Microdrive handling functions
=============================
Constants
---------
These are all #defines.
LIBSPECTRUM_MICRODRIVE_BLOCK_MAX
The maximum number of blocks which can be on a microdrive (254).
LIBSPECTRUM_MICRODRIVE_HEAD_LEN
The length in bytes of the header for a microdrive block in bytes
(15).
LIBSPECTRUM_MICRODRIVE_DATA_LEN
The length in bytes of the data for a microdrive block (512).
LIBSPECTRUM_MICRODRIVE_BLOCK_LEN
The total length in bytes of a microdrive block (2 *
LIBSPECTRUM_MICRODRIVE_HEAD_LEN + LIBSPECTRUM_MICRODRIVE_DATA_LEN + 1 =
543).
LIBSPECTRUM_MICRODRIVE_CARTRIDGE_LENGTH
The maximum length in bytes of a microdrive cartridge
(LIBSPECTRUM_MICRODRIVE_BLOCK_MAX * LIBSPECTRUM_MICRODRIVE_BLOCK_LEN =
137922).
Routines
--------
Routines for handling images of microdrive cartridges. As usual, these
are accessed through an opaque structure, libspectrum_microdrive.
libspectrum_microdrive*
libspectrum_microdrive_alloc( void )
Allocate a microdrive structure.
libspectrum_error
libspectrum_microdrive_free( libspectrum_microdrive *microdrive )
Free a microdrive structure.
libspectrum_byte
libspectrum_microdrive_data( const libspectrum_microdrive *microdrive,
size_t which )
void
libspectrum_microdrive_set_data( libspectrum_microdrive *microdrive,
size_t which, libspectrum_byte data )
Return or set (respectively) the byte of data at offset `which' into
the cartridge.
libspectrum_byte
libspectrum_microdrive_write_protect( const libspectrum_microdrive *microdrive )
void
libspectrum_microdrive_set_write_protect( libspectrum_microdrive *microdrive,
int write_protect )
Return or set the state of the write protect tab of the microdrive.
libspectrum_byte
libspectrum_microdrive_cartridge_len( const libspectrum_microdrive *microdrive )
void
libspectrum_microdrive_set_cartridge_len( libspectrum_microdrive *microdrive,
libspectrum_byte len )
Return or set the length in bytes of the cartridge in the drive.
int
libspectrum_microdrive_checksum( libspectrum_microdrive *microdrive,
libspectrum_byte which )
Check whether the checksum for the <n>th block on the microdrive is
correct, where <n> is specified by `which'.
.mdr file handling
------------------
libspectrum_error
libspectrum_microdrive_mdr_read( libspectrum_microdrive *microdrive,
libspectrum_byte *buffer, size_t length )
void
libspectrum_microdrive_mdr_write( const libspectrum_microdrive *microdrive,
libspectrum_byte **buffer, size_t *length )
Read and write an image of a microdrive cartridge to a .mdr file.
Timex dock/exrom handling functions
===================================
The Timex TS2068 and TC2068 featured a cartridge port (the `dock') for
which a few pieces of software were made available. The Warajevo
emulator includes support for this feature, and uses the `.dck'
extension for images of these cartridges. Documentation on this format
is available at
http://www.worldofspectrum.org/warajevo/Fformats.html#dck
Each .dck file can hold multiple 64Kb RAM banks, which are stored in a
`libspectrum_dck' structure:
typedef struct libspectrum_dck {
libspectrum_dck_block *dck[256];
} libspectrum_dck;
Each 64Kb bank is stored in a `libspectrum_dck_block' structure:
typedef struct libspectrum_dck_block {
libspectrum_dck_bank bank;
libspectrum_dck_page_type access[8];
libspectrum_byte *pages[8];
} libspectrum_dck_block;
The `bank' field specifies which type of memory this bank represents,
and takes one of the following values:
LIBSPECTRUM_DCK_BANK_DOCK The dock
LIBSPECTRUM_DCK_BANK_EXROM The EXROM
LIBSPECTRUM_DCK_BANK_HOME The normal memory space
The `access' field gives the type of memory stored in each 8Kb page
within the 64 Kb bank, and take be:
LIBSPECTRUM_DCK_PAGE_NULL Not present in this bank
LIBSPECTRUM_DCK_PAGE_RAM_EMPTY Uninitialised RAM
LIBSPECTRUM_DCK_PAGE_ROM ROM
LIBSPECTRUM_DCK_PAGE_RAM Initialised RAM
Any ROM or initialised RAM banks are in the `pages' field.
The actual routines for handling dock files:
libspectrum_dck* libspectrum_dck_alloc( void )
Allocate a dock structure.
libspectrum_error libspectrum_dck_free( libspectrum_dck *dck, int keep_pages )
Free a dock structure; if `keep_pages' is non-zero, any memory
allocated to the structure will not be freed and can then be used by
the calling program. Do remember to free it when you're finished with it!
libspectrum_error
libspectrum_dck_read( libspectrum_dck *dck, const libspectrum_byte *buffer,
size_t length )
Read in a dock structure from the `length' byte long `buffer'. Images
compressed with bzip2 or gzip will be automatically and transparently
decompressed.
IDE hard disk images
====================
Libspectrum contains various routines for handling IDE hard disk
images. Due to the (potential) large size of these files, hard disk
images are not handled entirely in memory as are the other file types,
but require a real file.
libspectrum_ide_channel*
libspectrum_ide_alloc( libspectrum_ide_databus databus )
Allocate a new IDE channel in `*chn' of type `databus'. `databus' can
take the following values:
LIBSPECTRUM_IDE_DATA8
A simple 8-bit interface which accesses only the low byte of each
word on the hard disk.
LIBSPECTRUM_IDE_DATA16
A full 16-bit interface which can access all data on the hard disk.
LIBSPECTRUM_IDE_DATA16_BYTESWAP
A full 16-bit interface which accesses the data in byte-swapped
order.
LIBSPECTRUM_IDE_DATA16_DATA2
A full 16-bit interface which returns the high byte of each word in
the secondary data register.
libspectrum_error
libspectrum_ide_free( libspectrum_ide_channel *chn )
Deallocate the IDE channel in `chn'.
libspectrum_error
libspectrum_ide_insert( libspectrum_ide_channel *chn,
libspectrum_ide_unit unit,
const char *filename )
Cause the IDE hard disk image in `filename' to be attached to `unit'
of the IDE channel `chn'. `unit' can take the following values:
LIBSPECTRUM_IDE_MASTER The IDE master unit
LIBSPECTRUM_IDE_SLAVE The IDE slave unit
libspectrum_error
libspectrum_ide_commit( libspectrum_ide_channel *chn,
libspectrum_ide_unit unit )
Cause any changes made to the image attached to `unit' of `chn' to be
written back to the image.
libspectrum_error
libspectrum_ide_eject( libspectrum_ide_channel *chn,
libspectrum_ide_unit unit )
Cause the image attached to `unit' of `chn' to be detached. Note that
any changes made to the image will be lost unless
`libspectrum_ide_commit' is called first.
libspectrum_error
libspectrum_ide_reset( libspectrum_ide_channel *chn )
Reset the IDE channel `chn'.
libspectrum_byte
libspectrum_ide_read( libspectrum_ide_channel *chn,
libspectrum_ide_register reg )
Returns the current value of register `reg' of the IDE channel
`chn'. `reg' can take the following values:
LIBSPECTRUM_IDE_REGISTER_DATA
LIBSPECTRUM_IDE_REGISTER_ERROR_FEATURE
LIBSPECTRUM_IDE_REGISTER_SECTOR_COUNT
LIBSPECTRUM_IDE_REGISTER_SECTOR
LIBSPECTRUM_IDE_REGISTER_CYLINDER_LOW
LIBSPECTRUM_IDE_REGISTER_CYLINDER_HIGH
LIBSPECTRUM_IDE_REGISTER_HEAD_DRIVE
LIBSPECTRUM_IDE_REGISTER_COMMAND_STATUS
LIBSPECTRUM_IDE_REGISTER_DATA2
The correspondence between these names and the actual IDE registers is
hopefully obvious; LIBSPECTRUM_IDE_REGISTER_DATA2 refers to the
secondary data register.
void
libspectrum_ide_write( libspectrum_ide_channel *chn,
libspectrum_ide_register reg, libspectrum_byte data )
Write `data' to register `reg' of the IDE channel `chn'.
MMC / SD card images
====================
Libspectrum contains various routines for handling MMC / SD card images. Due
to the (potential) large size of these files, hard disk images are not handled
entirely in memory as are the other file types, but require a real file.
Libspectrum re-uses the existing HDF file format for MMC / SD card images, and
emulates all cards as an SDHC card in SPI mode.
libspectrum_mmc_card*
libspectrum_mmc_alloc( void )
Allocate a new MMC card image.
void
libspectrum_mmc_free( libspectrum_mmc_card *card )
Deallocate the MMC card image in `card'.
libspectrum_error
libspectrum_mmc_insert( libspectrum_mmc_card *card, const char *filename );
Cause the MMC / SD card image in `filename' to be attached to `card'.
void
libspectrum_mmc_commit( libspectrum_mmc_card *card )
Cause any changes made to the image attached to `card' to be written back to
the image.
void
libspectrum_mmc_eject( libspectrum_mmc_card *card )
Cause the image attached to `card' to be detached. Note that any changes made
to the image will be lost unless `libspectrum_mmc_commit' is called first.
void
libspectrum_mmc_reset( libspectrum_mmc_card *card )
Reset the card `card'.
int
libspectrum_mmc_dirty( libspectrum_mmc_card *card )
Returns non-zero if any changes have been made to `card' since
`libspectrum_mmc_commit' was last called (or when the image was first loaded).
libspectrum_byte
libspectrum_mmc_read( libspectrum_mmc_card *card )
Read the next byte from the SPI bus for `card'.
void
libspectrum_mmc_write( libspectrum_mmc_card *card, libspectrum_byte data )
Write the byte `data` to the SPI bus for `card'.
Thread Safety
=============
libspectrum uses either glib or a libspectrum-supplied alternative as part of
the implementation of several internal data structures - notably in tape and
hard disk handling.
When glib is in use, the glib documentation[1] describes the threading support
as follows:
GLib itself is internally completely thread-safe (all global data is
automatically locked), but individual data structure instances are not
automatically locked for performance reasons. For example, you must coordinate
accesses to the same GHashTable from multiple threads.
When the glib replacement is in use, there are two modes of thread safety:
1. If the C11 header stdatomic.h is not available there is no locking of data
structures, and libspectrum should be considered to not be thread-safe
modifying any data structures
2. If the C11 header stdatomic.h is available the global data used in allocating
the list and hash table data structures are locked when changes are being
made but individual data structure instances are not automatically locked.
[1] <https://developer.gnome.org/glib/stable/glib-Threads.html>
|