Initial commit: akai-fetch - AKAI sampler ISO downloader & extractor
- fetch: Go CLI tool for searching, downloading, and extracting AKAI sampler ISOs from archive.org - scripts/extract_wavs.sh: Shell script driving akaiutil to convert samples to WAV - Dockerfile: Multi-stage build packaging akaiutil + fetch - third_party/akaiutil: Vendored akaiutil v4.6.7 source (GPLv2) - docs/akaiutil.md: Full akaiutil reference
This commit is contained in:
+28
@@ -0,0 +1,28 @@
|
|||||||
|
# Binaries
|
||||||
|
fetch
|
||||||
|
akai-fetch
|
||||||
|
akai-fetch-bin
|
||||||
|
*.exe
|
||||||
|
|
||||||
|
# Original akaiutil source (vendored copy in third_party/)
|
||||||
|
akaiutil-4.6.7/
|
||||||
|
|
||||||
|
# Build artifacts
|
||||||
|
*.o
|
||||||
|
*.obj
|
||||||
|
|
||||||
|
# Data
|
||||||
|
*.iso
|
||||||
|
output/
|
||||||
|
wavs
|
||||||
|
|
||||||
|
# IDE
|
||||||
|
.vscode/
|
||||||
|
.idea/
|
||||||
|
|
||||||
|
# OS
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
# Temp
|
||||||
|
/tmp/
|
||||||
+33
@@ -0,0 +1,33 @@
|
|||||||
|
# Stage 1: Build akaiutil from source
|
||||||
|
FROM debian:11 AS akaiutil-builder
|
||||||
|
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
build-essential \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
COPY third_party/akaiutil/ /src/akaiutil/
|
||||||
|
WORKDIR /src/akaiutil
|
||||||
|
RUN make
|
||||||
|
|
||||||
|
# Stage 2: Build fetch (Go tool)
|
||||||
|
FROM golang:1.26-alpine AS fetch-builder
|
||||||
|
|
||||||
|
WORKDIR /src
|
||||||
|
COPY go.mod main.go /src/
|
||||||
|
RUN CGO_ENABLED=0 go build -o /fetch .
|
||||||
|
|
||||||
|
# Stage 3: Runtime image
|
||||||
|
FROM debian:11-slim
|
||||||
|
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
bash \
|
||||||
|
ca-certificates \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
COPY --from=akaiutil-builder /src/akaiutil/akaiutil /usr/local/bin/
|
||||||
|
COPY --from=fetch-builder /fetch /usr/local/bin/fetch
|
||||||
|
COPY scripts/extract_wavs.sh /usr/local/bin/
|
||||||
|
|
||||||
|
WORKDIR /data
|
||||||
|
ENTRYPOINT ["fetch"]
|
||||||
|
CMD ["--help"]
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
BIN := fetch
|
||||||
|
IMAGE := akai-fetch
|
||||||
|
REMOTE := dhg.lol
|
||||||
|
|
||||||
|
build:
|
||||||
|
CGO_ENABLED=0 go build -o $(BIN) .
|
||||||
|
|
||||||
|
docker:
|
||||||
|
docker build -t $(IMAGE) .
|
||||||
|
|
||||||
|
docker-run:
|
||||||
|
docker run --rm -v "$(PWD)/output:/data" $(IMAGE) $(ARGS)
|
||||||
|
|
||||||
|
install: build
|
||||||
|
scp $(BIN) $(REMOTE):/tmp/$(BIN) && \
|
||||||
|
ssh $(REMOTE) "sudo mv /tmp/$(BIN) /DATA/Downloads/akai/$(BIN) && sudo chmod +x /DATA/Downloads/akai/$(BIN)"
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(BIN)
|
||||||
|
|
||||||
|
.PHONY: build docker docker-run install clean
|
||||||
@@ -0,0 +1,219 @@
|
|||||||
|
# akaiutil — AKAI Sampler Filesystem Tool
|
||||||
|
|
||||||
|
**Version 4.6.7** (21-OCT-2022) — GPLv2 — by Klaus Michael Indlekofer
|
||||||
|
|
||||||
|
Interactive console-based file manager for AKAI **S900/S950/S1000/S1100/S3000/CD3000** sampler disk images, floppies, hard drives, and CD-ROMs.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```
|
||||||
|
akaiutil [-h] [-r] [-F] [-C] [-l <lock-file>] [-o <start-offset>] [-s <pseudo-disk-size>]
|
||||||
|
[-n <pseudo-disk-number>] [-c <cdrom-index> ...] [-p <physdrive-index> ...]
|
||||||
|
[[-f] <floppy-drive>] ... [[-f] <disk-file>] ...
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
| Flag | Description |
|
||||||
|
|------|-------------|
|
||||||
|
| `-h` | Print help |
|
||||||
|
| `-r` | Read-only mode (must come first) |
|
||||||
|
| `-F` | Disable floppy filesystem detection |
|
||||||
|
| `-C` | Disable block cache |
|
||||||
|
| `-l <file>` | Lock file for exclusive access |
|
||||||
|
| `-o <offset>` | Byte offset where disk data starts (decimal or `0x` hex) |
|
||||||
|
| `-s <size>` | Pseudo-disk size in KB (for multi-disk images) |
|
||||||
|
| `-n <num>` | Max pseudo-disks per file descriptor (max 8) |
|
||||||
|
| `-c <n>` | (Windows) Open CD-ROM `\\.\cdromN` |
|
||||||
|
| `-p <n>` | (Windows) Open physical drive `\\.\physicaldriveN` |
|
||||||
|
|
||||||
|
On Linux, pass raw devices like `/dev/da1`, `/dev/disk2s0`.
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Open a floppy image
|
||||||
|
akaiutil fff.img
|
||||||
|
|
||||||
|
# Open harddisk images
|
||||||
|
akaiutil hhh1.img hhh2.img
|
||||||
|
|
||||||
|
# Multi-harddisk image with explicit size
|
||||||
|
akaiutil -s 524280 mmm.img
|
||||||
|
|
||||||
|
# Linux raw device access
|
||||||
|
akaiutil /dev/da1 hhh.img
|
||||||
|
|
||||||
|
# Read-only CD-ROM (macOS)
|
||||||
|
akaiutil -r /dev/disk2s0
|
||||||
|
```
|
||||||
|
|
||||||
|
## Virtual Filesystem
|
||||||
|
|
||||||
|
```
|
||||||
|
/disk<N>/<partition-letter>/<volume-name>/<file-name>
|
||||||
|
```
|
||||||
|
|
||||||
|
Shorthand: `/N` = `/diskN`, `/floppyN` = `/diskN/A/<volume1>`. Use `_` for spaces in names. `.` and `..` work as usual.
|
||||||
|
|
||||||
|
## Interactive Commands
|
||||||
|
|
||||||
|
### Navigation & Info
|
||||||
|
|
||||||
|
| Command | Alias | Description |
|
||||||
|
|---------|-------|-------------|
|
||||||
|
| `help [<cmd>]` | `man` | List commands or show help for a command |
|
||||||
|
| `exit` / `quit` | `bye`, `q` | Exit |
|
||||||
|
| `restart` | — | Rescan disks |
|
||||||
|
| `restartkeep` | `restart.`, `sync` | Rescan, keep current directory |
|
||||||
|
| `df` | — | Show disk info (all disks + partitions) |
|
||||||
|
| `dinfo` | `pwd` | Show current directory info |
|
||||||
|
| `cd [<path>]` | — | Change directory |
|
||||||
|
| `cdi <index>` | — | Change to volume by index |
|
||||||
|
| `dir [<path>]` | `ls` | List directory |
|
||||||
|
| `dirrec` | `lsrec` | Recursive listing |
|
||||||
|
| `lcd <path>` | — | Change local (host) directory |
|
||||||
|
| `ldir` | `lls` | List local directory |
|
||||||
|
| `dircache` | `lscache` | Show block cache info |
|
||||||
|
|
||||||
|
### File Operations
|
||||||
|
|
||||||
|
| Command | Alias | Description |
|
||||||
|
|---------|-------|-------------|
|
||||||
|
| `del <path>` / `deli <idx>` | `rm` / `rmi` | Delete file |
|
||||||
|
| `ren <old> <new> [<idx>]` | `mv` | Rename/move file |
|
||||||
|
| `reni <old-idx> <new> [<idx>]` | `mvi` | Rename by index |
|
||||||
|
| `copy <src> <dst> [<idx>]` | `cp` | Copy file |
|
||||||
|
| `copyi <src-idx> <dst> [<idx>]` | `cpi` | Copy by index |
|
||||||
|
| `infoi <idx>` | — | Show file info |
|
||||||
|
| `infoall` | — | Show info for all files |
|
||||||
|
|
||||||
|
### Import / Export
|
||||||
|
|
||||||
|
| Command | Alias | Description |
|
||||||
|
|---------|-------|-------------|
|
||||||
|
| `get <path> [<begin> [<end>]]` | `export` | Export file to host |
|
||||||
|
| `geti <idx> [<begin> [<end>]]` | `exporti` | Export by index |
|
||||||
|
| `getall` | `exportall` | Export all files |
|
||||||
|
| `put [<vol>/]<name> [<idx>]` | `import` | Import file (use `*` for all) |
|
||||||
|
| `getdisk <file>` | `dget`, `dexport` | Export entire disk image |
|
||||||
|
| `putdisk <file>` | `dput`, `dimport` | Import disk image |
|
||||||
|
| `getpart [<path>] <file>` | `pget`, `pexport` | Export partition |
|
||||||
|
| `putpart <file> [<path>]` | `pput`, `pimport` | Import partition |
|
||||||
|
| `gettags <file>` | `tagsget` | Export partition tags |
|
||||||
|
| `puttags <file>` | `tagsput` | Import partition tags |
|
||||||
|
|
||||||
|
### WAV Conversion
|
||||||
|
|
||||||
|
| Command | Alias | Description |
|
||||||
|
|---------|-------|-------------|
|
||||||
|
| `sample2wav <path>` / `sample2wavi <idx>` | `s2wav` / `getwav` | Sample → WAV |
|
||||||
|
| `sample2wavall` | `s2wavall` | All samples → WAV |
|
||||||
|
| `wav2sample <file> [<idx>]` | `wav2s`, `putwav` | WAV → sample (auto-detect) |
|
||||||
|
| `wav2sample9` / `wav2sample9c` | `putwav9` / `putwav9c` | WAV → S900 (non-compressed / compressed) |
|
||||||
|
| `wav2sample1` | `putwav1` | WAV → S1000 |
|
||||||
|
| `wav2sample3` | `putwav3` | WAV → S3000 |
|
||||||
|
|
||||||
|
WAV input must be mono/stereo, 8/16/24/32-bit PCM.
|
||||||
|
|
||||||
|
### S900 Compression
|
||||||
|
|
||||||
|
| Command | Alias | Description |
|
||||||
|
|---------|-------|-------------|
|
||||||
|
| `sample900compr <path>` | `s9compr` | Compress S900 sample |
|
||||||
|
| `sample900comprall` | `s9comprall` | Compress all S900 samples |
|
||||||
|
| `sample900uncompr <path>` | `s9uncompr` | Uncompress S900 sample |
|
||||||
|
| `sample900uncomprall` | `s9uncomprall` | Uncompress all |
|
||||||
|
|
||||||
|
### Volume Management
|
||||||
|
|
||||||
|
| Command | Alias | Description |
|
||||||
|
|---------|-------|-------------|
|
||||||
|
| `mkvol [<path>]` | `mkdir` | Create volume (auto-detect type) |
|
||||||
|
| `mkvol9` / `mkvol1` / `mkvol3` / `mkvol3cd` | `mkdir9` etc. | Create S900/S1000/S3000/CD3000 volume |
|
||||||
|
| `mkvoli <idx> [<name> [<load-num>]]` | `mkdiri` | Create volume at specific index |
|
||||||
|
| `delvol <path>` / `delvoli <idx>` | `rmdir` | Delete volume |
|
||||||
|
| `wipevol <path>` / `wipevoli <idx>` | `rmall` | Wipe all files in volume |
|
||||||
|
| `renvol <old> <new>` | `mvdir` | Rename volume |
|
||||||
|
| `copyvol <src> <dst>` / `copyvoli <idx> <dst>` | `cpvol` | Copy volume |
|
||||||
|
| `copypart <src> <dst>` | `cppart` | Copy all volumes of a partition |
|
||||||
|
| `setosvervol <ver>` / `setlnum <num>` | — | Set volume OS version / load number |
|
||||||
|
| `fixramname <path>` / `fixramnameall` | — | Fix file name headers |
|
||||||
|
|
||||||
|
### Volume Parameters
|
||||||
|
|
||||||
|
| Command | Alias | Description |
|
||||||
|
|---------|-------|-------------|
|
||||||
|
| `lsparam` / `lsparami <idx>` | — | List parameters |
|
||||||
|
| `initparam` / `initparami <idx>` | — | Initialize parameters |
|
||||||
|
| `setparam <idx> <val>` / `setparami <vidx> <pidx> <val>` | — | Set parameter |
|
||||||
|
| `getparam <file>` / `putparam <file>` | `paramget` / `paramput` | Export/import parameters |
|
||||||
|
|
||||||
|
### Tag Management
|
||||||
|
|
||||||
|
| Command | Description |
|
||||||
|
|---------|-------------|
|
||||||
|
| `lstags` | List tags |
|
||||||
|
| `inittags` | Initialize all tags |
|
||||||
|
| `rentag <idx> <name>` | Rename a tag |
|
||||||
|
| `settagi <file-idx> <tag-idx>` / `settagall <tag-idx>` | Tag a file / all files |
|
||||||
|
| `clrtagi <file-idx> <tag-idx or all>` / `clrtagall <tag or all>` | Untag |
|
||||||
|
| `setfiltertag <idx>` / `clrfiltertag <idx or all>` | Filter by tag |
|
||||||
|
|
||||||
|
### Formatting / Filesystem Operations
|
||||||
|
|
||||||
|
| Command | Description |
|
||||||
|
|---------|-------------|
|
||||||
|
| `formatfloppyl9` / `l1` / `l3` | Format low-density floppy for S900/S1000/S3000 |
|
||||||
|
| `formatfloppyh9` / `h1` / `h3` | Format high-density floppy |
|
||||||
|
| `wipefloppy` | Create filesystem on floppy |
|
||||||
|
| `formatharddisk9 [<size>]` | Format HD for S900 (SH205, SUPRA20M, SUPRA30M, SUPRA60M, or size) |
|
||||||
|
| `formatharddisk1 [<part-size> [<total-size>]]` | Format HD for S1000 |
|
||||||
|
| `formatharddisk3 [<part-size> [<total-size>]]` | Format HD for S3000 |
|
||||||
|
| `formatharddisk3cd [<part-size> [<total-size>]]` | Format CD3000 CD-ROM |
|
||||||
|
| `wipepart` / `wipepart3cd` | Create filesystem in partition |
|
||||||
|
| `fixpart` / `fixharddisk` | Fix filesystem |
|
||||||
|
| `scanbadblkspart` / `scanbadblksdisk` | Scan for bad blocks |
|
||||||
|
| `markbadblkspart` / `markbadblksdisk` | Mark free bad blocks |
|
||||||
|
| `setcdinfo [<label>]` / `cdinfo` / `vcdinfo` | CD3000 CD-ROM info |
|
||||||
|
|
||||||
|
### FAT / Direct-to-Disk Takes
|
||||||
|
|
||||||
|
| Command | Alias | Description |
|
||||||
|
|---------|-------|-------------|
|
||||||
|
| `tinfoi <idx>` / `tinfoall` | — | DD take info |
|
||||||
|
| `tdeli <idx>` | `trmi` | Delete DD take |
|
||||||
|
| `treni <idx> <name>` | `tmvi` | Rename DD take |
|
||||||
|
| `tgeti <idx>` / `tgetall` | `texporti` | Export DD take (`.TK`) |
|
||||||
|
| `tput <file>` | `timport` | Import DD take (`*.TK` for all) |
|
||||||
|
| `take2wavi <idx>` / `take2wavall` | `t2wavi`, `getwavti` | DD take → WAV |
|
||||||
|
| `wav2take <file>` | `wav2t`, `putwavt` | WAV → DD take |
|
||||||
|
|
||||||
|
### Tar Archives
|
||||||
|
|
||||||
|
| Command | Alias | Description |
|
||||||
|
|---------|-------|-------------|
|
||||||
|
| `tarc <file>` | `gettar` | Create tar from current directory |
|
||||||
|
| `tarcwav <file>` | `gettarwav` | Tar-create with WAV conversion |
|
||||||
|
| `tarx <file>` | `puttar` | Extract tar (auto-detect type) |
|
||||||
|
| `tarx9` / `tarx1` / `tarx3` / `tarx3cd` | `puttar9` etc. | Extract as specific type |
|
||||||
|
| `tarxwav` | `puttarwav` | Extract with WAV → sample conversion |
|
||||||
|
| `tarxwav9` / `tarxwav9c` / `tarxwav1` / `tarxwav3` | — | Extract WAV as specific sampler type |
|
||||||
|
|
||||||
|
## Filesystem Types
|
||||||
|
|
||||||
|
| Type | Description | Block Size | Max Size / Blocks |
|
||||||
|
|------|-------------|------------|-------------------|
|
||||||
|
| FLL | Low-density floppy | 1 KB | 800 KB (800 blocks) |
|
||||||
|
| FLH | High-density floppy | 1 KB | 1600 KB (1600 blocks) |
|
||||||
|
| HD9 | S900/S950 harddisk | 8 KB | ~64 MB (8191 blocks) |
|
||||||
|
| HD | S1000/S3000 partition | 8 KB | 60 MB/partition, ~512 MB total |
|
||||||
|
| DD | S1100/S3000 Direct-to-Disk | 8 KB | ~512 MB |
|
||||||
|
|
||||||
|
## Build
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make
|
||||||
|
```
|
||||||
|
|
||||||
|
Produces the `akaiutil` binary.
|
||||||
@@ -0,0 +1,596 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
|
"sort"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
iaSearchURL = "https://archive.org/advancedsearch.php"
|
||||||
|
iaBaseURL = "https://archive.org"
|
||||||
|
userAgent = "akai-fetch/1.0"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SearchResult struct {
|
||||||
|
Response struct {
|
||||||
|
NumFound int `json:"numFound"`
|
||||||
|
Docs []SearchDoc `json:"docs"`
|
||||||
|
} `json:"response"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type SearchDoc struct {
|
||||||
|
Identifier string `json:"identifier"`
|
||||||
|
Title string `json:"title"`
|
||||||
|
Downloads int `json:"downloads"`
|
||||||
|
Format []string `json:"format"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type MetadataResult struct {
|
||||||
|
Files []MetadataFile `json:"files"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type MetadataFile struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Size string `json:"size"`
|
||||||
|
Format string `json:"format"`
|
||||||
|
Source string `json:"source"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
if len(os.Args) < 2 {
|
||||||
|
printUsage()
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd := os.Args[1]
|
||||||
|
args := os.Args[2:]
|
||||||
|
|
||||||
|
switch cmd {
|
||||||
|
case "search":
|
||||||
|
cmdSearch(args)
|
||||||
|
case "list":
|
||||||
|
cmdList(args)
|
||||||
|
case "download":
|
||||||
|
cmdDownload(args)
|
||||||
|
case "extract":
|
||||||
|
cmdExtract(args)
|
||||||
|
case "pipeline":
|
||||||
|
cmdPipeline(args)
|
||||||
|
default:
|
||||||
|
fmt.Fprintf(os.Stderr, "unknown command: %s\n", cmd)
|
||||||
|
printUsage()
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func printUsage() {
|
||||||
|
fmt.Println(`akai-fetch — AKAI sampler ISO downloader & extractor
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
akai-fetch search [flags] search archive.org for AKAI sampler ISOs
|
||||||
|
akai-fetch list <identifier> list downloadable ISO files in an item
|
||||||
|
akai-fetch download [flags] download ISOs (from file or by identifier)
|
||||||
|
akai-fetch extract [flags] extract WAVs from downloaded ISOs
|
||||||
|
akai-fetch pipeline [flags] full search → download → extract pipeline
|
||||||
|
|
||||||
|
Search flags:
|
||||||
|
-query "akai sampler" search query (default: "subject:akai AND subject:sampler")
|
||||||
|
-filter "term" extra term AND-ed onto the query (e.g. "vocal")
|
||||||
|
-limit 30 max results (default: 30)
|
||||||
|
-min-downloads 0 minimum download count filter
|
||||||
|
|
||||||
|
Download flags:
|
||||||
|
-i "identifier" archive.org item identifier
|
||||||
|
-f "file.txt" file with list of identifiers (one per line)
|
||||||
|
-dir "./isos" output directory (default: current dir)
|
||||||
|
-jobs 2 concurrent downloads (default: 2)
|
||||||
|
|
||||||
|
Extract flags:
|
||||||
|
-dir "./isos" directory containing ISO files
|
||||||
|
-out "./wavs" output directory for WAV files
|
||||||
|
-tool "./extract_wavs.sh" path to extraction script
|
||||||
|
-jobs 2 concurrent extractions (default: 2)
|
||||||
|
|
||||||
|
Pipeline flags:
|
||||||
|
-query "akai sampler" search query (default: "subject:akai AND subject:sampler")
|
||||||
|
-filter "term" extra term AND-ed onto the query
|
||||||
|
-limit 30 max results
|
||||||
|
-dir "./output" base output directory
|
||||||
|
-download-jobs 2 concurrent downloads
|
||||||
|
-extract-jobs 2 concurrent extractions`)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─── Search ────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
func cmdSearch(args []string) {
|
||||||
|
fs := flag.NewFlagSet("search", flag.ExitOnError)
|
||||||
|
query := fs.String("query", "subject:akai AND subject:sampler", "search query")
|
||||||
|
filter := fs.String("filter", "", "extra term AND-ed onto the query")
|
||||||
|
limit := fs.Int("limit", 30, "max results")
|
||||||
|
minDL := fs.Int("min-downloads", 0, "minimum download count")
|
||||||
|
_ = fs.Parse(args)
|
||||||
|
|
||||||
|
q := *query
|
||||||
|
if *filter != "" {
|
||||||
|
q = "(" + q + ") AND (" + *filter + ")"
|
||||||
|
}
|
||||||
|
|
||||||
|
results := searchArchive(q, *limit)
|
||||||
|
sort.Slice(results, func(i, j int) bool {
|
||||||
|
return results[i].Downloads > results[j].Downloads
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Printf("Found %d items:\n\n", len(results))
|
||||||
|
for _, r := range results {
|
||||||
|
if *minDL > 0 && r.Downloads < *minDL {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fmt.Printf(" %-40s downloads: %-8d title: %s\n", r.Identifier, r.Downloads, truncate(r.Title, 50))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func searchArchive(query string, limit int) []SearchDoc {
|
||||||
|
params := url.Values{}
|
||||||
|
params.Set("q", query)
|
||||||
|
params.Set("fl[]", "identifier,title,downloads,format")
|
||||||
|
params.Set("sort[]", "downloads desc")
|
||||||
|
params.Set("rows", strconv.Itoa(limit))
|
||||||
|
params.Set("page", "1")
|
||||||
|
params.Set("output", "json")
|
||||||
|
|
||||||
|
u := iaSearchURL + "?" + params.Encode()
|
||||||
|
client := &http.Client{Timeout: 30 * time.Second}
|
||||||
|
req, err := http.NewRequest("GET", u, nil)
|
||||||
|
if err != nil {
|
||||||
|
fatal("http request: %v", err)
|
||||||
|
}
|
||||||
|
req.Header.Set("User-Agent", userAgent)
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
fatal("search request: %v", err)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
body, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
fatal("read response: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var sr SearchResult
|
||||||
|
if err := json.Unmarshal(body, &sr); err != nil {
|
||||||
|
fatal("parse response: %v", err)
|
||||||
|
}
|
||||||
|
return sr.Response.Docs
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─── List ──────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
func cmdList(args []string) {
|
||||||
|
if len(args) < 1 {
|
||||||
|
fatal("usage: akai-fetch list <identifier>")
|
||||||
|
}
|
||||||
|
identifier := args[0]
|
||||||
|
files := getItemFiles(identifier)
|
||||||
|
|
||||||
|
fmt.Printf("Files in %s:\n\n", identifier)
|
||||||
|
for _, f := range files {
|
||||||
|
size := f.Size
|
||||||
|
if size == "" {
|
||||||
|
size = "?"
|
||||||
|
}
|
||||||
|
fmt.Printf(" %-60s %s\n", f.Name, size)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getItemFiles(identifier string) []MetadataFile {
|
||||||
|
u := fmt.Sprintf("%s/metadata/%s", iaBaseURL, url.PathEscape(identifier))
|
||||||
|
client := &http.Client{Timeout: 30 * time.Second}
|
||||||
|
req, _ := http.NewRequest("GET", u, nil)
|
||||||
|
req.Header.Set("User-Agent", userAgent)
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
fatal("metadata request: %v", err)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
body, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
fatal("read metadata: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var mr struct {
|
||||||
|
Files []MetadataFile `json:"files"`
|
||||||
|
}
|
||||||
|
if err := json.Unmarshal(body, &mr); err != nil {
|
||||||
|
fatal("parse metadata: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var isos []MetadataFile
|
||||||
|
for _, f := range mr.Files {
|
||||||
|
if strings.HasSuffix(strings.ToLower(f.Name), ".iso") {
|
||||||
|
isos = append(isos, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return isos
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─── Download ──────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
type downloadJob struct {
|
||||||
|
Identifier string
|
||||||
|
Name string
|
||||||
|
URL string
|
||||||
|
OutPath string
|
||||||
|
Size int64
|
||||||
|
}
|
||||||
|
|
||||||
|
func cmdDownload(args []string) {
|
||||||
|
fs := flag.NewFlagSet("download", flag.ExitOnError)
|
||||||
|
identifier := fs.String("i", "", "archive.org item identifier")
|
||||||
|
idFile := fs.String("f", "", "file with identifiers (one per line)")
|
||||||
|
outDir := fs.String("dir", ".", "output directory")
|
||||||
|
jobs := fs.Int("jobs", 2, "concurrent downloads")
|
||||||
|
_ = fs.Parse(args)
|
||||||
|
|
||||||
|
os.MkdirAll(*outDir, 0755)
|
||||||
|
|
||||||
|
var identifiers []string
|
||||||
|
if *identifier != "" {
|
||||||
|
identifiers = append(identifiers, *identifier)
|
||||||
|
}
|
||||||
|
if *idFile != "" {
|
||||||
|
data, err := os.ReadFile(*idFile)
|
||||||
|
if err != nil {
|
||||||
|
fatal("read id file: %v", err)
|
||||||
|
}
|
||||||
|
for _, line := range strings.Split(string(data), "\n") {
|
||||||
|
line = strings.TrimSpace(line)
|
||||||
|
if line != "" && !strings.HasPrefix(line, "#") {
|
||||||
|
identifiers = append(identifiers, line)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(identifiers) == 0 {
|
||||||
|
fatal("provide -i <identifier> or -f <file>")
|
||||||
|
}
|
||||||
|
|
||||||
|
var jobsList []downloadJob
|
||||||
|
for _, id := range identifiers {
|
||||||
|
files := getItemFiles(id)
|
||||||
|
if len(files) == 0 {
|
||||||
|
fmt.Printf("[%s] no ISO files found\n", id)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for _, f := range files {
|
||||||
|
size, _ := strconv.ParseInt(f.Size, 10, 64)
|
||||||
|
jobsList = append(jobsList, downloadJob{
|
||||||
|
Identifier: id,
|
||||||
|
Name: f.Name,
|
||||||
|
URL: fmt.Sprintf("%s/download/%s/%s", iaBaseURL, url.PathEscape(id), url.PathEscape(f.Name)),
|
||||||
|
OutPath: filepath.Join(*outDir, f.Name),
|
||||||
|
Size: size,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(jobsList) == 0 {
|
||||||
|
fmt.Println("no download jobs")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Downloading %d file(s) with %d concurrent job(s)...\n\n", len(jobsList), *jobs)
|
||||||
|
|
||||||
|
var mu sync.Mutex
|
||||||
|
sem := make(chan struct{}, *jobs)
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
var totalDownloaded int64
|
||||||
|
|
||||||
|
for _, job := range jobsList {
|
||||||
|
wg.Add(1)
|
||||||
|
go func(j downloadJob) {
|
||||||
|
defer wg.Done()
|
||||||
|
sem <- struct{}{}
|
||||||
|
defer func() { <-sem }()
|
||||||
|
|
||||||
|
size, err := downloadFile(j)
|
||||||
|
mu.Lock()
|
||||||
|
totalDownloaded += size
|
||||||
|
mu.Unlock()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf(" FAIL %-40s %v\n", j.Name, err)
|
||||||
|
} else {
|
||||||
|
fmt.Printf(" OK %-40s %s\n", j.Name, humanSize(size))
|
||||||
|
}
|
||||||
|
}(job)
|
||||||
|
}
|
||||||
|
wg.Wait()
|
||||||
|
fmt.Printf("\nDownloaded %s total\n", humanSize(totalDownloaded))
|
||||||
|
}
|
||||||
|
|
||||||
|
func downloadFile(job downloadJob) (int64, error) {
|
||||||
|
// Check if file already exists and has the expected size
|
||||||
|
if fi, err := os.Stat(job.OutPath); err == nil {
|
||||||
|
if job.Size > 0 && fi.Size() == job.Size {
|
||||||
|
return fi.Size(), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if partial file exists for resume
|
||||||
|
var existingSize int64
|
||||||
|
if fi, err := os.Stat(job.OutPath); err == nil {
|
||||||
|
existingSize = fi.Size()
|
||||||
|
}
|
||||||
|
|
||||||
|
client := &http.Client{Timeout: 0}
|
||||||
|
req, err := http.NewRequest("GET", job.URL, nil)
|
||||||
|
if err != nil {
|
||||||
|
return 0, fmt.Errorf("request: %w", err)
|
||||||
|
}
|
||||||
|
req.Header.Set("User-Agent", userAgent)
|
||||||
|
if existingSize > 0 {
|
||||||
|
req.Header.Set("Range", fmt.Sprintf("bytes=%d-", existingSize))
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return 0, fmt.Errorf("get: %w", err)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusPartialContent {
|
||||||
|
return 0, fmt.Errorf("HTTP %d", resp.StatusCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
outFile, err := os.OpenFile(job.OutPath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
|
||||||
|
if err != nil {
|
||||||
|
return 0, fmt.Errorf("open: %w", err)
|
||||||
|
}
|
||||||
|
defer outFile.Close()
|
||||||
|
|
||||||
|
written, err := io.Copy(outFile, resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return 0, fmt.Errorf("download: %w", err)
|
||||||
|
}
|
||||||
|
return written + existingSize, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─── Extract ───────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
func cmdExtract(args []string) {
|
||||||
|
fs := flag.NewFlagSet("extract", flag.ExitOnError)
|
||||||
|
isoDir := fs.String("dir", ".", "directory with ISO files")
|
||||||
|
outDir := fs.String("out", "./wavs", "output directory for WAVs")
|
||||||
|
toolPath := fs.String("tool", "./extract_wavs.sh", "path to extraction script")
|
||||||
|
jobs := fs.Int("jobs", 2, "concurrent extractions")
|
||||||
|
_ = fs.Parse(args)
|
||||||
|
|
||||||
|
entries, err := os.ReadDir(*isoDir)
|
||||||
|
if err != nil {
|
||||||
|
fatal("read dir: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var isos []string
|
||||||
|
for _, e := range entries {
|
||||||
|
if !e.IsDir() && strings.HasSuffix(strings.ToLower(e.Name()), ".iso") {
|
||||||
|
isos = append(isos, filepath.Join(*isoDir, e.Name()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(isos) == 0 {
|
||||||
|
fmt.Println("no ISO files found in", *isoDir)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Extracting %d ISO(s) with %d concurrent job(s)...\n", len(isos), *jobs)
|
||||||
|
|
||||||
|
sem := make(chan struct{}, *jobs)
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
var mu sync.Mutex
|
||||||
|
results := map[string]string{}
|
||||||
|
|
||||||
|
for _, iso := range isos {
|
||||||
|
wg.Add(1)
|
||||||
|
go func(isoPath string) {
|
||||||
|
defer wg.Done()
|
||||||
|
sem <- struct{}{}
|
||||||
|
defer func() { <-sem }()
|
||||||
|
|
||||||
|
out := *outDir
|
||||||
|
result, err := extractISO(*toolPath, isoPath, out)
|
||||||
|
mu.Lock()
|
||||||
|
results[filepath.Base(isoPath)] = result
|
||||||
|
mu.Unlock()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf(" FAIL %-40s %v\n", filepath.Base(isoPath), err)
|
||||||
|
} else {
|
||||||
|
fmt.Printf(" OK %-40s %s\n", filepath.Base(isoPath), result)
|
||||||
|
}
|
||||||
|
}(iso)
|
||||||
|
}
|
||||||
|
wg.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
func extractISO(toolPath, isoPath, outDir string) (string, error) {
|
||||||
|
absTool, err := filepath.Abs(toolPath)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if _, err := os.Stat(absTool); os.IsNotExist(err) {
|
||||||
|
return "", fmt.Errorf("script not found: %s", absTool)
|
||||||
|
}
|
||||||
|
|
||||||
|
isoOutDir := filepath.Join(outDir, sanitiseISOName(filepath.Base(isoPath)))
|
||||||
|
|
||||||
|
if _, err := os.Stat(isoOutDir); err == nil {
|
||||||
|
var wavCount int
|
||||||
|
filepath.WalkDir(isoOutDir, func(p string, d os.DirEntry, err error) error {
|
||||||
|
if err == nil && !d.IsDir() && strings.HasSuffix(strings.ToLower(d.Name()), ".wav") {
|
||||||
|
wavCount++
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if wavCount > 0 {
|
||||||
|
return fmt.Sprintf("skipped (%d WAVs exist)", wavCount), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd := exec.Command("bash", absTool, isoPath, outDir)
|
||||||
|
cmd.Stderr = nil
|
||||||
|
output, err := cmd.Output()
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("extract: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
lines := strings.Split(string(output), "\n")
|
||||||
|
for _, line := range lines {
|
||||||
|
if strings.Contains(line, "Total WAV files:") {
|
||||||
|
return strings.TrimSpace(line), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "extracted (check output)", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func sanitiseISOName(path string) string {
|
||||||
|
name := path
|
||||||
|
if ext := filepath.Ext(name); ext != "" {
|
||||||
|
name = name[:len(name)-len(ext)]
|
||||||
|
}
|
||||||
|
// Matches extract_wavs.sh sanitisation
|
||||||
|
var buf strings.Builder
|
||||||
|
for _, r := range name {
|
||||||
|
if r == ' ' {
|
||||||
|
buf.WriteRune('_')
|
||||||
|
} else if (r >= 'a' && r <= 'z') || (r >= 'A' && r <= 'Z') ||
|
||||||
|
(r >= '0' && r <= '9') || r == '_' || r == '.' || r == '-' {
|
||||||
|
buf.WriteRune(r)
|
||||||
|
} else {
|
||||||
|
buf.WriteRune('_')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Collapse multiple underscores
|
||||||
|
s := buf.String()
|
||||||
|
for strings.Contains(s, "__") {
|
||||||
|
s = strings.ReplaceAll(s, "__", "_")
|
||||||
|
}
|
||||||
|
// Strip leading/trailing _ and .
|
||||||
|
s = strings.Trim(s, "_.")
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─── Pipeline ──────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
func cmdPipeline(args []string) {
|
||||||
|
fs := flag.NewFlagSet("pipeline", flag.ExitOnError)
|
||||||
|
query := fs.String("query", "subject:akai AND subject:sampler", "search query")
|
||||||
|
filter := fs.String("filter", "", "extra term AND-ed onto the query")
|
||||||
|
limit := fs.Int("limit", 10, "max results")
|
||||||
|
baseDir := fs.String("dir", "./output", "base output directory")
|
||||||
|
dlJobs := fs.Int("download-jobs", 2, "concurrent downloads")
|
||||||
|
extJobs := fs.Int("extract-jobs", 2, "concurrent extractions")
|
||||||
|
_ = fs.Parse(args)
|
||||||
|
|
||||||
|
isoDir := filepath.Join(*baseDir, "isos")
|
||||||
|
wavDir := filepath.Join(*baseDir, "wavs")
|
||||||
|
toolPath := filepath.Join(filepath.Dir(os.Args[0]), "extract_wavs.sh")
|
||||||
|
|
||||||
|
if _, err := os.Stat(toolPath); os.IsNotExist(err) {
|
||||||
|
cwd, _ := os.Getwd()
|
||||||
|
toolPath = filepath.Join(cwd, "extract_wavs.sh")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remaining args after flags are treated as explicit identifiers
|
||||||
|
identifiers := fs.Args()
|
||||||
|
|
||||||
|
if len(identifiers) == 0 {
|
||||||
|
fmt.Println("=== Phase 1: Search ===")
|
||||||
|
q := *query
|
||||||
|
if *filter != "" {
|
||||||
|
q = "(" + q + ") AND (" + *filter + ")"
|
||||||
|
}
|
||||||
|
fmt.Printf("Query: %s Limit: %d\n\n", q, *limit)
|
||||||
|
results := searchArchive(q, *limit)
|
||||||
|
sort.Slice(results, func(i, j int) bool {
|
||||||
|
return results[i].Downloads > results[j].Downloads
|
||||||
|
})
|
||||||
|
if len(results) == 0 {
|
||||||
|
fmt.Println("No results found.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, r := range results {
|
||||||
|
identifiers = append(identifiers, r.Identifier)
|
||||||
|
}
|
||||||
|
fmt.Printf("Found %d items\n\n", len(identifiers))
|
||||||
|
} else {
|
||||||
|
fmt.Printf("=== Processing %d specific item(s) ===\n\n", len(identifiers))
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := os.MkdirAll(*baseDir, 0755); err != nil {
|
||||||
|
fatal("create output dir: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
idFile := filepath.Join(*baseDir, "identifiers.txt")
|
||||||
|
var idContent strings.Builder
|
||||||
|
for _, id := range identifiers {
|
||||||
|
idContent.WriteString(id + "\n")
|
||||||
|
}
|
||||||
|
if err := os.WriteFile(idFile, []byte(idContent.String()), 0644); err != nil {
|
||||||
|
fatal("write ids: %v", err)
|
||||||
|
}
|
||||||
|
fmt.Printf("Identifiers saved to %s\n\n", idFile)
|
||||||
|
|
||||||
|
fmt.Println("=== Phase 2: Download ===")
|
||||||
|
cmdDownload([]string{"-f", idFile, "-dir", isoDir, "-jobs", fmt.Sprintf("%d", *dlJobs)})
|
||||||
|
|
||||||
|
fmt.Println("\n=== Phase 3: Extract ===")
|
||||||
|
cmdExtract([]string{"-dir", isoDir, "-out", wavDir, "-tool", toolPath, "-jobs", fmt.Sprintf("%d", *extJobs)})
|
||||||
|
|
||||||
|
fmt.Printf("\n=== Pipeline Complete ===\n")
|
||||||
|
fmt.Printf(" ISOs: %s\n", isoDir)
|
||||||
|
fmt.Printf(" WAVs: %s\n", wavDir)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─── Helpers ───────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
func fatal(format string, args ...any) {
|
||||||
|
fmt.Fprintf(os.Stderr, "error: "+format+"\n", args...)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func truncate(s string, n int) string {
|
||||||
|
if len(s) <= n {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
return s[:n-3] + "..."
|
||||||
|
}
|
||||||
|
|
||||||
|
func humanSize(bytes int64) string {
|
||||||
|
const unit = 1024
|
||||||
|
if bytes < unit {
|
||||||
|
return fmt.Sprintf("%dB", bytes)
|
||||||
|
}
|
||||||
|
div, exp := int64(unit), 0
|
||||||
|
for n := bytes / unit; n >= unit; n /= unit {
|
||||||
|
div *= unit
|
||||||
|
exp++
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%.1f %cB", float64(bytes)/float64(div), "KMGTPE"[exp])
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
// Ensure we can parse flags even with -count or other test flags
|
||||||
|
flag.CommandLine.Parse([]string{})
|
||||||
|
}
|
||||||
Executable
+115
@@ -0,0 +1,115 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Extract all AKAI samples as WAV from all volumes in an AKAI disk image.
|
||||||
|
# Usage: ./extract_wavs.sh <iso-file> [output-dir]
|
||||||
|
# Uses a single akaiutil session to avoid repeated disk rescans.
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
AKAIUTIL="${AKAIUTIL:-akaiutil}"
|
||||||
|
ISO="${1:?Usage: $0 <iso-file> [output-dir]}"
|
||||||
|
OUTPUT="${2:-wavs}"
|
||||||
|
|
||||||
|
# Derive ISO basename without extension, sanitized for filesystem use
|
||||||
|
isobase=$(basename "$ISO")
|
||||||
|
isobase="${isobase%.*}"
|
||||||
|
isobase=$(echo "$isobase" | sed 's/ /_/g' | sed 's/[^A-Za-z0-9_.-]/_/g' | sed 's/__*/_/g' | sed 's/^[_.]//; s/[_.]$//')
|
||||||
|
OUTPUT="$OUTPUT/$isobase"
|
||||||
|
|
||||||
|
TMPFILE=$(mktemp /tmp/akai_cmds.XXXXXX)
|
||||||
|
trap 'rm -f "$TMPFILE"' EXIT
|
||||||
|
|
||||||
|
mkdir -p "$OUTPUT"
|
||||||
|
|
||||||
|
# Phase 1: enumerate partitions from df output
|
||||||
|
echo "Enumerating partitions and volumes..."
|
||||||
|
DF_OUTPUT=$("$AKAIUTIL" -r "$ISO" 2>/dev/null <<< $'df\nq')
|
||||||
|
|
||||||
|
# Parse partition letters from the partition table in df output
|
||||||
|
PARTITIONS=()
|
||||||
|
while IFS= read -r line; do
|
||||||
|
if [[ "$line" =~ ^[[:space:]]+([A-Z])[[:space:]]+ ]]; then
|
||||||
|
PARTITIONS+=("${BASH_REMATCH[1]}")
|
||||||
|
fi
|
||||||
|
done <<< "$DF_OUTPUT"
|
||||||
|
|
||||||
|
if [[ ${#PARTITIONS[@]} -eq 0 ]]; then
|
||||||
|
echo "No partitions found in ISO. Trying single-partition layout..."
|
||||||
|
PARTITIONS=("A")
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Found partitions: ${PARTITIONS[*]}"
|
||||||
|
|
||||||
|
# Scan each partition for volumes
|
||||||
|
VOLUME_LIST=$(
|
||||||
|
{
|
||||||
|
for p in "${PARTITIONS[@]}"; do
|
||||||
|
echo "cd /disk0/$p"
|
||||||
|
echo "dir"
|
||||||
|
done
|
||||||
|
echo "q"
|
||||||
|
} | "$AKAIUTIL" -r "$ISO" 2>/dev/null
|
||||||
|
)
|
||||||
|
|
||||||
|
# Parse partition-letter:volume-name pairs
|
||||||
|
VOLUMES=()
|
||||||
|
CURRENT_PART=""
|
||||||
|
while IFS= read -r line; do
|
||||||
|
for p in "${PARTITIONS[@]}"; do
|
||||||
|
if [[ "$line" == *"/disk0/$p >"* ]]; then
|
||||||
|
CURRENT_PART="$p"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if [[ "$line" =~ ^[[:space:]]+[0-9]+[[:space:]]+(.+)[[:space:]]+-[[:space:]]+ ]]; then
|
||||||
|
name="${BASH_REMATCH[1]}"
|
||||||
|
name="${name%% -*}"
|
||||||
|
name="$(echo "$name" | sed 's/ *$//')"
|
||||||
|
if [[ -n "$CURRENT_PART" && -n "$name" ]]; then
|
||||||
|
VOLUMES+=("$CURRENT_PART|$name")
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done <<< "$VOLUME_LIST"
|
||||||
|
|
||||||
|
echo "Found ${#VOLUMES[@]} volumes"
|
||||||
|
|
||||||
|
# Phase 2: build command file and create output dirs
|
||||||
|
> "$TMPFILE"
|
||||||
|
|
||||||
|
for entry in "${VOLUMES[@]}"; do
|
||||||
|
IFS='|' read -r part vol_name <<< "$entry"
|
||||||
|
|
||||||
|
safe_name=$(echo "$vol_name" | sed 's/ /_/g' | sed 's/[^A-Za-z0-9_.-]/_/g' | sed 's/__*/_/g' | sed 's/^[_.]//; s/[_.]$//')
|
||||||
|
[[ -z "$safe_name" ]] && safe_name="volume"
|
||||||
|
|
||||||
|
vol_dir="$OUTPUT/$safe_name"
|
||||||
|
mkdir -p "$vol_dir"
|
||||||
|
|
||||||
|
nav_name="${vol_name// /_}"
|
||||||
|
echo "lcd $vol_dir" >> "$TMPFILE"
|
||||||
|
echo "cd /disk0/$part/$nav_name" >> "$TMPFILE"
|
||||||
|
echo "sample2wavall" >> "$TMPFILE"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "lcd /" >> "$TMPFILE"
|
||||||
|
echo "q" >> "$TMPFILE"
|
||||||
|
|
||||||
|
# Phase 3: run extraction
|
||||||
|
echo "Starting extraction..."
|
||||||
|
START=$SECONDS
|
||||||
|
"$AKAIUTIL" -r "$ISO" < "$TMPFILE" 2>/dev/null > /tmp/akai_output.txt
|
||||||
|
DURATION=$((SECONDS - START))
|
||||||
|
|
||||||
|
total=0
|
||||||
|
while IFS= read -r line; do
|
||||||
|
if [[ "$line" =~ exported[[:space:]]+([0-9]+)[[:space:]]+file ]]; then
|
||||||
|
count="${BASH_REMATCH[1]}"
|
||||||
|
total=$((total + count))
|
||||||
|
echo " -> $count WAVs"
|
||||||
|
fi
|
||||||
|
done < /tmp/akai_output.txt
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "--- Done in ${DURATION}s ---"
|
||||||
|
echo "Total WAV files: $total"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "WAVs are in: $OUTPUT/"
|
||||||
+76
@@ -0,0 +1,76 @@
|
|||||||
|
# Copyright (c) 2008-2022 Klaus Michael Indlekofer. All rights reserved.
|
||||||
|
#
|
||||||
|
# m.indlekofer@gmx.de
|
||||||
|
#
|
||||||
|
# This program 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 2
|
||||||
|
# of the License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program 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 this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
VERSION = 4.6.7
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
CFLAGS += -Wall -Wextra -O2
|
||||||
|
ifdef FILE_OFFSET_BITS_64
|
||||||
|
CFLAGS += -D_FILE_OFFSET_BITS=64
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
all: akaiutil
|
||||||
|
|
||||||
|
install:
|
||||||
|
$(INSTALL_PROGRAM) akaiutil $(PREFIX)/bin/
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f akaiutil akaiutil.exe *.o *.obj
|
||||||
|
|
||||||
|
back:
|
||||||
|
mkdir -p akaiutil-$(VERSION);\
|
||||||
|
cp -p Makefile Makefile.nmake README.txt gpl*.txt *.c *.h *.vcproj *.sln *.dsw *.dsp akaiutil-$(VERSION);\
|
||||||
|
tar -clvpzf akaiutil-$(VERSION).tar.gz akaiutil-$(VERSION)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
akaiutil: akaiutil_main.o akaiutil_tar.o akaiutil_file.o akaiutil_take.o akaiutil_wav.o akaiutil.o akaiutil_io.o commonlib.o
|
||||||
|
$(CC) $(CFLAGS) -o $@ akaiutil_main.o akaiutil_tar.o akaiutil_file.o akaiutil_take.o akaiutil_wav.o akaiutil.o akaiutil_io.o commonlib.o -lm
|
||||||
|
|
||||||
|
akaiutil_main.o: akaiutil_main.c akaiutil.h akaiutil_io.h akaiutil_tar.h akaiutil_file.h akaiutil_take.h commoninclude.h
|
||||||
|
$(CC) $(CFLAGS) -c akaiutil_main.c
|
||||||
|
|
||||||
|
akaiutil_tar.o: akaiutil_tar.c akaiutil_tar.h akaiutil_file.h akaiutil_take.h akaiutil.h akaiutil_io.h commoninclude.h
|
||||||
|
$(CC) $(CFLAGS) -c akaiutil_tar.c
|
||||||
|
|
||||||
|
akaiutil_file.o: akaiutil_file.c akaiutil_file.h akaiutil_wav.h akaiutil.h commoninclude.h
|
||||||
|
$(CC) $(CFLAGS) -c akaiutil_file.c
|
||||||
|
|
||||||
|
akaiutil_take.o: akaiutil_take.c akaiutil_take.h akaiutil_wav.h akaiutil.h akaiutil_io.h commoninclude.h
|
||||||
|
$(CC) $(CFLAGS) -c akaiutil_take.c
|
||||||
|
|
||||||
|
akaiutil_wav.o: akaiutil_wav.c akaiutil_wav.h commoninclude.h
|
||||||
|
$(CC) $(CFLAGS) -c akaiutil_wav.c
|
||||||
|
|
||||||
|
akaiutil.o: akaiutil.c akaiutil.h akaiutil_io.h akaiutil_file.h commoninclude.h
|
||||||
|
$(CC) $(CFLAGS) -c akaiutil.c
|
||||||
|
|
||||||
|
akaiutil_io.o: akaiutil_io.c akaiutil_io.h commoninclude.h
|
||||||
|
$(CC) $(CFLAGS) -c akaiutil_io.c
|
||||||
|
|
||||||
|
commonlib.o: commonlib.c commoninclude.h
|
||||||
|
$(CC) $(CFLAGS) -c commonlib.c
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# EOF
|
||||||
+63
@@ -0,0 +1,63 @@
|
|||||||
|
# Copyright (c) 2008-2021 Klaus Michael Indlekofer. All rights reserved.
|
||||||
|
#
|
||||||
|
# m.indlekofer@gmx.de
|
||||||
|
#
|
||||||
|
# This program 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 2
|
||||||
|
# of the License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program 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 this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
CFLAGS = $(CFLAGS) /nologo /O2 /D_VISUALCPP /D_CRT_SECURE_NO_DEPRECATE
|
||||||
|
|
||||||
|
LIBS = $(LIBS) Winmm.lib
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
all: akaiutil.exe
|
||||||
|
|
||||||
|
clean:
|
||||||
|
del /q /f akaiutil.exe *.obj
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
akaiutil.exe: akaiutil_main.obj akaiutil_tar.obj akaiutil_file.obj akaiutil_take.obj akaiutil_wav.obj akaiutil.obj akaiutil_io.obj commonlib.obj
|
||||||
|
$(CC) $(CFLAGS) /Fe$@ akaiutil_main.obj akaiutil_tar.obj akaiutil_file.obj akaiutil_take.obj akaiutil_wav.obj akaiutil.obj akaiutil_io.obj commonlib.obj $(LIBS)
|
||||||
|
|
||||||
|
akaiutil_main.obj: akaiutil_main.c akaiutil.h akaiutil_io.h akaiutil_tar.h akaiutil_file.h akaiutil_take.h commoninclude.h
|
||||||
|
$(CC) $(CFLAGS) /c akaiutil_main.c
|
||||||
|
|
||||||
|
akaiutil_tar.obj: akaiutil_tar.c akaiutil_tar.h akaiutil_file.h akaiutil_take.h akaiutil.h akaiutil_io.h commoninclude.h
|
||||||
|
$(CC) $(CFLAGS) /c akaiutil_tar.c
|
||||||
|
|
||||||
|
akaiutil_file.obj: akaiutil_file.c akaiutil_file.h akaiutil_wav.h akaiutil.h commoninclude.h
|
||||||
|
$(CC) $(CFLAGS) /c akaiutil_file.c
|
||||||
|
|
||||||
|
akaiutil_take.obj: akaiutil_take.c akaiutil_take.h akaiutil_wav.h akaiutil.h akaiutil_io.h commoninclude.h
|
||||||
|
$(CC) $(CFLAGS) /c akaiutil_take.c
|
||||||
|
|
||||||
|
akaiutil_wav.obj: akaiutil_wav.c akaiutil_wav.h commoninclude.h
|
||||||
|
$(CC) $(CFLAGS) /c akaiutil_wav.c
|
||||||
|
|
||||||
|
akaiutil.obj: akaiutil.c akaiutil.h akaiutil_io.h akaiutil_file.h commoninclude.h
|
||||||
|
$(CC) $(CFLAGS) /c akaiutil.c
|
||||||
|
|
||||||
|
akaiutil_io.obj: akaiutil_io.c akaiutil_io.h commoninclude.h
|
||||||
|
$(CC) $(CFLAGS) /c akaiutil_io.c
|
||||||
|
|
||||||
|
commonlib.obj: commonlib.c commoninclude.h
|
||||||
|
$(CC) $(CFLAGS) /c commonlib.c
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# EOF
|
||||||
+755
@@ -0,0 +1,755 @@
|
|||||||
|
akaiutil: access to AKAI S900/S1000/S3000 filesystems
|
||||||
|
Copyright (c) 2008-2022 by Klaus Michael Indlekofer. All rights reserved.
|
||||||
|
Note: Special restrictions apply. See disclaimers below and within the distribution.
|
||||||
|
|
||||||
|
Release akaiutil-4.6.7 (21-OCT-2022)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Email: m.indlekofer@gmx.de
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
------
|
||||||
|
|
||||||
|
akaiutil [-h] [-r] [-F] [-C] [-l <lock-file>] [-o <start-offset>] [-s <pseudo-disk-size>] [-n <pseudo-disk-number>] [-c <cdrom-index> ...] [-p <physdrive-index> ...] [[-f] <floppy-drive> ...] [[-f] <disk-file> ...]
|
||||||
|
-h print this info
|
||||||
|
-r read-only mode
|
||||||
|
-F disable floppy filesystem for disk-files/CD-ROM drives/physical drives
|
||||||
|
-C disable cache
|
||||||
|
-l lock-file
|
||||||
|
-o set start offset for disk-file/drive in bytes
|
||||||
|
-s set pseudo-disk size in KB
|
||||||
|
-n set max. number of pseudo-disks per disk-file/drive
|
||||||
|
-c CD-ROM drive
|
||||||
|
-p physical drive
|
||||||
|
-f floppy drive or disk-file
|
||||||
|
<floppy-drive> = floppyla: | floppylb: | floppyha: | floppyhb:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Commands:
|
||||||
|
---------
|
||||||
|
|
||||||
|
help [<cmd>] print help information for a command
|
||||||
|
=man
|
||||||
|
|
||||||
|
exit exit program
|
||||||
|
=quit
|
||||||
|
=bye
|
||||||
|
=q
|
||||||
|
|
||||||
|
restart restart program (with opened disks)
|
||||||
|
|
||||||
|
restartkeep restart program (with opened disks, keep current directory path etc.)
|
||||||
|
=restart.
|
||||||
|
=sync
|
||||||
|
|
||||||
|
df print disk info
|
||||||
|
|
||||||
|
dinfo print current directory info
|
||||||
|
=pwd
|
||||||
|
|
||||||
|
cd [<path>] change current directory
|
||||||
|
|
||||||
|
cdi <volume-index> change current volume
|
||||||
|
|
||||||
|
dir [<path>] list directory
|
||||||
|
=ls
|
||||||
|
|
||||||
|
dirrec list current directory recursively
|
||||||
|
=lsrec
|
||||||
|
|
||||||
|
lstags list tags in partition
|
||||||
|
=dirtags
|
||||||
|
|
||||||
|
inittags initialize tags of disk or partition
|
||||||
|
|
||||||
|
rentag <tag-index> <tag-name> rename tag in partition
|
||||||
|
|
||||||
|
cdinfo print CD3000 CD-ROM info
|
||||||
|
|
||||||
|
vcdinfo print verbose CD3000 CD-ROM info
|
||||||
|
|
||||||
|
setcdinfo [<cdlabel>] set CD3000 CD-ROM info of disk or partition
|
||||||
|
|
||||||
|
lcd <dir-path> change current local (external) directory
|
||||||
|
|
||||||
|
ldir list files in current local (external) directory
|
||||||
|
=lls
|
||||||
|
|
||||||
|
lsfat print FAT of current partition
|
||||||
|
|
||||||
|
lsfati <file-index> print FAT-chain of file
|
||||||
|
|
||||||
|
lstfati <take-index> print FAT-chain of DD take
|
||||||
|
|
||||||
|
infoi <file-index> print information for file
|
||||||
|
|
||||||
|
infoall print information for all files in current volume
|
||||||
|
|
||||||
|
tinfoi <take-index> print information for DD take
|
||||||
|
|
||||||
|
tinfoall print information for all DD takes in current partition
|
||||||
|
|
||||||
|
del <file-path> delete file
|
||||||
|
=rm
|
||||||
|
|
||||||
|
deli <file-index> delete file
|
||||||
|
rmi
|
||||||
|
|
||||||
|
tdeli <take-index> delete DD take
|
||||||
|
trmi
|
||||||
|
|
||||||
|
ren <old-file-path> <new-file-path> [<new-file-index>] rename/move file
|
||||||
|
=mv
|
||||||
|
|
||||||
|
reni <old-file-index> <new-file-path> [<new-file-index>] rename/move file
|
||||||
|
=mvi
|
||||||
|
|
||||||
|
setosveri <file-index> <new-os-version> set OS version of file in S1000/S3000 volume
|
||||||
|
|
||||||
|
setosverall <new-os-version> set OS version of all files in current S1000/S3000 volume
|
||||||
|
|
||||||
|
setuncompri <file-index> <new-uncompr> set uncompr value of compressed file in S900 volume
|
||||||
|
|
||||||
|
updateuncompri <file-index> update uncompr value of compressed file in S900 volume
|
||||||
|
|
||||||
|
updateuncomprall update uncompr value of all compressed files in current S900 volume
|
||||||
|
|
||||||
|
sample900uncompr <file-path> [<dest-vol-path>] uncompress S900 compressed sample file
|
||||||
|
=s9uncompr
|
||||||
|
|
||||||
|
sample900uncompri <file-index> [<dest-vol-path>] uncompress S900 compressed sample file
|
||||||
|
=s9uncompri
|
||||||
|
|
||||||
|
sample900uncomprall [<dest-vol-path>] uncompress all S900 compressed sample files in current volume
|
||||||
|
=s9uncomprall
|
||||||
|
|
||||||
|
sample900compr <file-path> [<dest-vol-path>] compress S900 non-compressed sample file
|
||||||
|
=s9compr
|
||||||
|
|
||||||
|
sample900compri <file-index> [<dest-vol-path>] compress S900 non-compressed sample file
|
||||||
|
=s9compri
|
||||||
|
|
||||||
|
sample900comprall [<dest-vol-path>] compress all S900 non-compressed sample files in current volume
|
||||||
|
=s9comprall
|
||||||
|
|
||||||
|
fixramname <file-path> fix name in file header
|
||||||
|
|
||||||
|
fixramnamei <file-index> fix name in file header
|
||||||
|
|
||||||
|
fixramnameall fix name in file header of all files in current volume
|
||||||
|
|
||||||
|
clrtagi <file-index> {<tag-index>|all} untag file
|
||||||
|
|
||||||
|
clrtagall {<tag-index>|all} untag all files in current volume
|
||||||
|
|
||||||
|
settagi <file-index> <tag-index> tag file
|
||||||
|
|
||||||
|
settagall <tag-index> tag all files in current volume
|
||||||
|
|
||||||
|
treni <take-index> <new-name> rename DD take
|
||||||
|
=tmvi
|
||||||
|
|
||||||
|
clrfiltertag {<tag-index>|all} remove tag from file filter
|
||||||
|
|
||||||
|
setfiltertag <tag-index> add tag to file filter
|
||||||
|
|
||||||
|
copy <src-file-path> <new-file-path> [<new-file-index>] copy file
|
||||||
|
=cp
|
||||||
|
|
||||||
|
copyi <src-file-index> <new-file-path> [<new-file-index>] copy file
|
||||||
|
=cpi
|
||||||
|
|
||||||
|
copyvol <src-volume-path> <new-volume-path> copy volume (with all of its files)
|
||||||
|
=cpvol
|
||||||
|
|
||||||
|
copyvoli <src-volume-index> <new-volume-path> copy volume (with all of its files)
|
||||||
|
=cpvoli
|
||||||
|
|
||||||
|
copypart <src-partition-path> <dst-partition-path> copy all volumes of a partition
|
||||||
|
=cppart
|
||||||
|
|
||||||
|
copytags <src-partition-path> <dst-partition-path> copy all tags of a partition
|
||||||
|
=cptags
|
||||||
|
|
||||||
|
wipevol <volume-path> delete all files in volume
|
||||||
|
=wipedir
|
||||||
|
=rmall
|
||||||
|
|
||||||
|
wipevoli <volume-index> delete all files in volume
|
||||||
|
=wipediri
|
||||||
|
=rmalli
|
||||||
|
|
||||||
|
delvol <volume-path> delete volume and all of its files
|
||||||
|
=deldir
|
||||||
|
=rmvol
|
||||||
|
=rmdir
|
||||||
|
|
||||||
|
delvoli <volume-index> delete volume and all of its files
|
||||||
|
=deldiri
|
||||||
|
=rmvoli
|
||||||
|
=rmdiri
|
||||||
|
|
||||||
|
formatfloppyl9 format/erase low-density floppy for S900/S950, create filesystem
|
||||||
|
=formatfl9
|
||||||
|
|
||||||
|
formatfloppyl1 format/erase low-density floppy for S1000, create filesystem
|
||||||
|
=formatfl1
|
||||||
|
|
||||||
|
formatfloppyl3 format/erase low-density floppy for S3000, create filesystem
|
||||||
|
=formatfl3
|
||||||
|
|
||||||
|
formatfloppyh9 format/erase high-density floppy for S950, create filesystem
|
||||||
|
=formatfh9
|
||||||
|
|
||||||
|
formatfloppyh1 format/erase high-density floppy for S1000, create filesystem
|
||||||
|
=formatfh1
|
||||||
|
|
||||||
|
formatfloppyh3 format/erase high-density floppy for S3000, create filesystem
|
||||||
|
=formatfh3
|
||||||
|
|
||||||
|
wipefloppy create filesystem on floppy
|
||||||
|
=newfsfloppy
|
||||||
|
|
||||||
|
formatharddisk9 [<total-size>[M]|SH205|SUPRA20M|SUPRA30M|SUPRA60M] create filesystem on harddisk for S900/S950 (size in blocks or MB, or drive name)
|
||||||
|
=formathd9
|
||||||
|
=newfsharddisk9
|
||||||
|
=newfshd9
|
||||||
|
|
||||||
|
formatharddisk1 [<part-size>[M] [<total-size>[M]]] create filesystem on harddisk for S1000 (size in blocks or MB)
|
||||||
|
=formathd1
|
||||||
|
=newfsharddisk9
|
||||||
|
=newfshd1
|
||||||
|
|
||||||
|
formatharddisk3 [<part-size>[M] [<total-size>[M]]] create filesystem on harddisk for S3000 or CD3000 (size in blocks or MB)
|
||||||
|
=formathd3
|
||||||
|
=newfsharddisk3
|
||||||
|
=newfshd3
|
||||||
|
|
||||||
|
formatharddisk3cd [<part-size>[M] [<total-size>[M]]] create filesystem on harddisk for CD3000 CD-ROM (size in blocks or MB)
|
||||||
|
=formatcd
|
||||||
|
=newfsharddisk3cd
|
||||||
|
=newfscd
|
||||||
|
|
||||||
|
wipepart [<partition-path>] create filesystem in harddisk partition
|
||||||
|
=newfspart
|
||||||
|
|
||||||
|
wipepart3cd [<partition-path>] create filesystem in harddisk partition for CD3000 CD-ROM
|
||||||
|
=newfspart3cd
|
||||||
|
|
||||||
|
fixpart [<partition-path>] fix filesystem in harddisk partition
|
||||||
|
|
||||||
|
fixharddisk [<disk-path>] fix filesystem on harddisk
|
||||||
|
|
||||||
|
scanbadblkspart [<partition-path>] scan for bad blocks/clusters in partition
|
||||||
|
|
||||||
|
markbadblkspart [<partition-path>] mark free bad blocks/clusters in partition
|
||||||
|
|
||||||
|
scanbadblksdisk [<disk-path>] scan for bad blocks/clusters in all partitions of disk
|
||||||
|
|
||||||
|
markbadblksdisk [<disk-path>] mark free bad blocks/clusters in all partitions of disk
|
||||||
|
|
||||||
|
getdisk <file-name> get disk (to external file)
|
||||||
|
=dget
|
||||||
|
=dexport
|
||||||
|
|
||||||
|
putdisk <file-name> put disk (from external file)
|
||||||
|
=dput
|
||||||
|
=dimport
|
||||||
|
|
||||||
|
getpart [<partition-path>] <file-name> get partition (to external file)
|
||||||
|
=pget
|
||||||
|
=pexport
|
||||||
|
|
||||||
|
putpart <file-name> [<partition-path>] put partition (from external file)
|
||||||
|
=pput
|
||||||
|
=pimport
|
||||||
|
|
||||||
|
gettags <file-name> get tags from partition (to external file)
|
||||||
|
=tagsget
|
||||||
|
=tagsexport
|
||||||
|
|
||||||
|
puttags <file-name> put tags to partition (from external file)
|
||||||
|
=tagsput
|
||||||
|
=tagsimport
|
||||||
|
|
||||||
|
renvol <old-path> <new-name> rename volume
|
||||||
|
=rendir
|
||||||
|
=mvvol
|
||||||
|
=mvdir
|
||||||
|
|
||||||
|
renvoli <volume-index> <new-name> rename volume
|
||||||
|
=rendiri
|
||||||
|
=mvvoli
|
||||||
|
=mvdiri
|
||||||
|
|
||||||
|
setosvervol <new-os-version> set OS version of current volume
|
||||||
|
|
||||||
|
setosvervoli <volume-index> <new-os-version> set OS version of volume
|
||||||
|
|
||||||
|
setlnum <new-load-number> set load number of current volume (OFF for none)
|
||||||
|
|
||||||
|
setlnumi <volume-index> <new-load-number> set load number of volume (OFF for none)
|
||||||
|
|
||||||
|
lsparam list parameters in current volume
|
||||||
|
|
||||||
|
lsparami <volume-index> list parameters in volume
|
||||||
|
|
||||||
|
initparam initialize parameters in current volume
|
||||||
|
|
||||||
|
initparami <volume-index> initialize parameters in volume
|
||||||
|
|
||||||
|
setparam <par-index> <par-value> set parameters in current volume
|
||||||
|
|
||||||
|
setparami <volume-index> <par-index> <par-value> set parameters in volume
|
||||||
|
|
||||||
|
getparam <file-name> get parameters from current volume (to external file)
|
||||||
|
=paramget
|
||||||
|
=paramexport
|
||||||
|
|
||||||
|
getparami <volume-index> <file-name> get parameters from volume (to external file)
|
||||||
|
=paramgeti
|
||||||
|
=paramexporti
|
||||||
|
|
||||||
|
putparam <file-name> put parameters to current volume (from external file)
|
||||||
|
=paramput
|
||||||
|
=paramimport
|
||||||
|
|
||||||
|
putparami <volume-index> <file-name> put parameters to volume (from external file)
|
||||||
|
=paramputi
|
||||||
|
=paramimporti
|
||||||
|
|
||||||
|
get <file-path> [<begin-byte> [<end-byte>]] get file (to external)
|
||||||
|
=export
|
||||||
|
|
||||||
|
geti <file-index> [<begin-byte> [<end-byte>]] get file (to external)
|
||||||
|
=exporti
|
||||||
|
|
||||||
|
getall get all files (to external)
|
||||||
|
=exportall
|
||||||
|
|
||||||
|
sample2wav <file-path> convert sample file into external WAV file
|
||||||
|
=s2wav
|
||||||
|
=getwav
|
||||||
|
|
||||||
|
sample2wavi <file-index> convert sample file into external WAV file
|
||||||
|
=s2wavi
|
||||||
|
=getwavi
|
||||||
|
|
||||||
|
sample2wavall convert all sample files into external WAV files
|
||||||
|
=s2wavall
|
||||||
|
=getwavall
|
||||||
|
|
||||||
|
put [<volume-path>/]<file-name> [<file-index>] put file (from external, use * for all local files)
|
||||||
|
=import
|
||||||
|
|
||||||
|
wav2sample [<volume-path>/]<wav-file> [<file-index>] convert external WAV file into sample file (use *.wav for all local WAV files)
|
||||||
|
=wav2s
|
||||||
|
=putwav
|
||||||
|
|
||||||
|
wav2sample9 [<volume-path>/]<wav-file> [<file-index>] convert external WAV file into S900 non-compressed sample file (use *.wav for all local WAV files)
|
||||||
|
=wav2s9
|
||||||
|
=putwav9
|
||||||
|
|
||||||
|
wav2sample9c [<volume-path>/]<wav-file> [<file-index>] convert external WAV file into S900 compressed sample file (use *.wav for all local WAV files)
|
||||||
|
=wav2s9c
|
||||||
|
=putwav9c
|
||||||
|
|
||||||
|
wav2sample1 [<volume-path>/]<wav-file> [<file-index>] convert external WAV file into S1000 sample file (use *.wav for all local WAV files)
|
||||||
|
=wav2s1
|
||||||
|
=putwav1
|
||||||
|
|
||||||
|
wav2sample3 [<volume-path>/]<wav-file> [<file-index>] convert external WAV file into S3000 sample file (use *.wav for all local WAV files)
|
||||||
|
=wav2s3
|
||||||
|
=putwav3
|
||||||
|
|
||||||
|
tgeti <take-index> get DD take (to external)
|
||||||
|
=texporti
|
||||||
|
|
||||||
|
tgetall get all DD takes (to external)
|
||||||
|
=texportall
|
||||||
|
|
||||||
|
take2wavi <take-index> convert DD take into external WAV file
|
||||||
|
=t2wavi
|
||||||
|
=tgetwavi
|
||||||
|
=getwavti
|
||||||
|
|
||||||
|
take2wavall convert all DD takes into external WAV files
|
||||||
|
=t2wavall
|
||||||
|
=tgetwavall
|
||||||
|
=getwavtall
|
||||||
|
|
||||||
|
tput <take-file> put DD take (from external, use *.TK for all local DD take files)
|
||||||
|
=timport
|
||||||
|
|
||||||
|
wav2take <wav-file> convert external WAV file into DD take (use *.wav for all local WAV files)
|
||||||
|
=wav2t
|
||||||
|
=tputwav
|
||||||
|
=putwavt
|
||||||
|
|
||||||
|
tarc <tar-file> tar c from current directory (to external)
|
||||||
|
=target
|
||||||
|
=gettar
|
||||||
|
|
||||||
|
tarcwav <tar-file> tar c from current directory (to external) with WAV conversion
|
||||||
|
=targetwav
|
||||||
|
=gettarwav
|
||||||
|
|
||||||
|
tarx <tar-file> tar x in current directory (from external)
|
||||||
|
=tarput
|
||||||
|
=puttar
|
||||||
|
|
||||||
|
tarx9 <tar-file> tar x in current directory (from external) for S900
|
||||||
|
=tarput9
|
||||||
|
=puttar9
|
||||||
|
|
||||||
|
tarx1 <tar-file> tar x in current directory (from external) for S1000
|
||||||
|
=tarput1
|
||||||
|
=puttar1
|
||||||
|
|
||||||
|
tarx3 <tar-file> tar x in current directory (from external) for S3000 or CD3000
|
||||||
|
=tarput3
|
||||||
|
=puttar3
|
||||||
|
|
||||||
|
tarx3cd <tar-file> tar x in current directory (from external) for CD3000 CD-ROM
|
||||||
|
=tarput3cd
|
||||||
|
=puttar3cd
|
||||||
|
|
||||||
|
tarxwav <tar-file> tar x in current directory (from external) with WAV conversion
|
||||||
|
=tarputwav
|
||||||
|
=puttarwav
|
||||||
|
|
||||||
|
tarxwav9 <tar-file> tar x in current directory (from external) with WAV conversion to S900 non-compressed sample
|
||||||
|
=tarputwav9
|
||||||
|
=puttarwav9
|
||||||
|
|
||||||
|
tarxwav9c <tar-file> tar x in current directory (from external) with WAV conversion to S900 compressed sample
|
||||||
|
=tarputwav9c
|
||||||
|
=puttarwav9c
|
||||||
|
|
||||||
|
tarxwav1 <tar-file> tar x in current directory (from external) with WAV conversion to S1000 sample
|
||||||
|
=tarputwav1
|
||||||
|
=puttarwav1
|
||||||
|
|
||||||
|
tarxwav3 <tar-file> tar x in current directory (from external) with WAV conversion to S3000 sample
|
||||||
|
=tarputwav3
|
||||||
|
=puttarwav3
|
||||||
|
|
||||||
|
mkvol [<volume-path>] create new volume
|
||||||
|
=mkdir
|
||||||
|
|
||||||
|
mkvol9 [<volume-path>] create new volume for S900
|
||||||
|
=mkdir9
|
||||||
|
|
||||||
|
mkvol1 [<volume-path> [<load-number>]] create new volume for S1000
|
||||||
|
=mkdir1
|
||||||
|
|
||||||
|
mkvol3 [<volume-path> [<load-number>]] create new volume for S3000 or CD3000
|
||||||
|
=mkdir3
|
||||||
|
|
||||||
|
mkvol3cd [<volume-path> [<load-number>]] create new volume for CD3000 CD-ROM
|
||||||
|
=mkdir3cd
|
||||||
|
|
||||||
|
mkvoli <volume-index> [<volume-name> [<load-number>]] create new volume at index
|
||||||
|
=mkdiri
|
||||||
|
|
||||||
|
mkvoli9 <volume-index> [<volume-name>] create new volume for S900 at index
|
||||||
|
=mkdiri9
|
||||||
|
|
||||||
|
mkvoli1 <volume-index> [<volume-name> [<load-number>]] create new volume for S1000 at index
|
||||||
|
=mkdiri1
|
||||||
|
|
||||||
|
mkvoli3 <volume-index> [<volume-name> [<load-number>]] create new volume for S3000 or CD3000 at index
|
||||||
|
=mkdiri3
|
||||||
|
|
||||||
|
mkvoli3cd <volume-index> [<volume-name> [<load-number>]] create new volume for CD3000 CD-ROM
|
||||||
|
=mkdiri3cd
|
||||||
|
|
||||||
|
dircache print cache information
|
||||||
|
=lscache
|
||||||
|
|
||||||
|
disablecache disable cache
|
||||||
|
|
||||||
|
enablecache enable cache
|
||||||
|
|
||||||
|
lock acquire lock
|
||||||
|
|
||||||
|
unlock release lock
|
||||||
|
|
||||||
|
playwav [<wav-file>] start playback of current external WAV file
|
||||||
|
=p
|
||||||
|
|
||||||
|
stopwav stop playback of current external WAV file
|
||||||
|
=s
|
||||||
|
|
||||||
|
delwav delete current external WAV file
|
||||||
|
=rmwav
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
---------
|
||||||
|
|
||||||
|
Example 1: access floppy image fff.img
|
||||||
|
akaiutil.exe fff.img
|
||||||
|
|
||||||
|
Example 2: access harddisk images hhh1.img and hhh2.img
|
||||||
|
akaiutil.exe hhh1.img hhh2.img
|
||||||
|
|
||||||
|
Example 3: access harddisk image hhh.img and floppy image fff.img
|
||||||
|
akaiutil.exe hhh.img fff.img
|
||||||
|
|
||||||
|
Example 4: access multi-harddisk image mmm.img with pseudo-disks of 524280KB
|
||||||
|
akaiutil.exe -s 524280 mmm.img
|
||||||
|
|
||||||
|
Example 5: access high-density (HD) floppy in floppy drive A: on Windows PC:
|
||||||
|
akaiutil.exe floppyha:
|
||||||
|
|
||||||
|
Example 6: access Windows physical drive 1 and Windows CD-ROM drive 0
|
||||||
|
akaiutil.exe -p 1 -c 0
|
||||||
|
|
||||||
|
Example 7: access Windows physical drive 2, harddisk image hhh.img, and floppy image fff.img
|
||||||
|
akaiutil.exe -p 2 hhh.img fff.img
|
||||||
|
|
||||||
|
Example 8: access UNIX harddisks /dev/da1, /dev/da2, and harddisk image hhh.img
|
||||||
|
akaiutil /dev/da1 /dev/da2 hhh.img
|
||||||
|
|
||||||
|
Example 9: access Darwin harddisk /dev/disk1
|
||||||
|
akaiutil /dev/disk1
|
||||||
|
|
||||||
|
Example 10: access Darwin CD-ROM /dev/disk2s0 in read-only mode
|
||||||
|
akaiutil -r /dev/disk2s0
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Warning:
|
||||||
|
--------
|
||||||
|
|
||||||
|
Accessing disk-files or floppies or physical drives might destroy their contents!!! Use at your own risk!!!
|
||||||
|
It is strongly recommended to use the read-only mode (-r) for testing and for accessing valuable drives, floppies, or files.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
------
|
||||||
|
|
||||||
|
* whole (pseudo-)disks can be imported/exported via "putdisk"/"getdisk"
|
||||||
|
* whole partitions can be imported/exported via "putpart"/"getpart"
|
||||||
|
* individual files can be imported/exported via "put"/"get"
|
||||||
|
* sample files can be exported to external WAV files via "sample2wav", "sample2wavall"
|
||||||
|
* DD takes can be exported to external WAV files via "take2wav", "take2wavall"
|
||||||
|
* external WAV files can be imported to sample files via "wav2sample", "wav2sample9", "wav2sample1","wav2sample3"
|
||||||
|
WAV files for sample import must be mono or stereo, and in 8bit or 16bit or 24bit or 32bit PCM format
|
||||||
|
* external WAV files can be imported to DD takes via "wav2take"
|
||||||
|
WAV files for DD take import must be mono or stereo, and in 8bit or 16bit or 24bit or 32bit PCM format
|
||||||
|
* the current external WAV file (e.g. previously exported via "sample2wav" or "take2wav") can be played back via "playwav"
|
||||||
|
* individual files can be copied via "copy"
|
||||||
|
* whole volumes and partitions can be copied via "copyvol" and "copypart"
|
||||||
|
* whole directory trees can be imported/exported from/to tar archives via "tarput"/"target"
|
||||||
|
* WAV file conversion for tar archives via "tarputwav"/"targetwav"
|
||||||
|
* file path names in akaiutil are of the form "/disk/partition/volume/file", e.g. "/disk2/C/VOLUME_007/SINE.S"
|
||||||
|
* for access to files/volumes via index, some commands have an "i" version
|
||||||
|
* abbreviations:
|
||||||
|
".." = one level up, "." = stay in same directory
|
||||||
|
"/N" = "/diskN"
|
||||||
|
"/floppyN" = "/diskN/A/<volume1>"
|
||||||
|
'_' can be used as a typable replacement for ' ' (space) in file or volume names
|
||||||
|
* if the pseudo-disk size ("-s" option) and the max. number of pseudo-disks ("-n" option) are both specified,
|
||||||
|
the given values are taken and the usable disk size is not determined automatically,
|
||||||
|
which might be useful e.g. for accessing harddisks which have bad blocks
|
||||||
|
* for shared access to drives or disk-files,
|
||||||
|
it might be useful to disable the cache (via the "-C" option or via the "disablecache" command),
|
||||||
|
and the "restartkeep" command can be used to rescan disks/partitions/volumes,
|
||||||
|
and a lock-file ("-l" option and "lock"/"unlock" commands) can be used for exclusive access
|
||||||
|
* for detailed information about individual akaiutil commands please read the online help infos
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Floppy drives:
|
||||||
|
--------------
|
||||||
|
|
||||||
|
In order to access a floppy drive to format, read, or write an AKAI floppy on a Windows PC,
|
||||||
|
fdrawcmd.sys (by Simon Owen, see https://simonowen.com/fdrawcmd/) has to be installed.
|
||||||
|
|
||||||
|
Floppy drive arguments for akaiutil running on a Windows PC:
|
||||||
|
"floppyla:" for low-density (DD) floppy in drive A:
|
||||||
|
"floppylb:" for low-density (DD) floppy in drive B:
|
||||||
|
"floppyha:" for high-density (HD) floppy in drive A:
|
||||||
|
"floppyhb:" for high-density (HD) floppy in drive B:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Formatting drives and images:
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
Low-density (DD) floppy size: 800 blocks (1KB) = 800KB
|
||||||
|
|
||||||
|
High-density (HD) floppy size: 1600 blocks (1KB) = 1600KB
|
||||||
|
|
||||||
|
Max. S900/S950 harddisk (or CD-ROM) size: 8191 blocks (8KB) = 65528KB = approx. 64MB
|
||||||
|
|
||||||
|
S900/S950 standard harddisk sizes:
|
||||||
|
2601 blocks (8KB) = 20808KB ("Atari SH205")
|
||||||
|
2500 blocks (8KB) = 20000KB ("Supra 20M")
|
||||||
|
3812 blocks (8KB) = 30496KB ("Supra 30M")
|
||||||
|
7624 blocks (8KB) = 60992KB ("Supra 60M")
|
||||||
|
|
||||||
|
Max. S1000/S3000 harddisk (or CD-ROM) size: 65535 blocks (8KB) = 524280KB = approx. 512MB
|
||||||
|
|
||||||
|
S1000/S3000 standard harddisk partition sizes:
|
||||||
|
3840 blocks (8KB) = 30720KB = 30MB
|
||||||
|
5120 blocks (8KB) = 40960KB = 40MB
|
||||||
|
6400 blocks (8KB) = 51200KB = 50MB
|
||||||
|
7680 blocks (8KB) = 61440KB = 60MB
|
||||||
|
|
||||||
|
ZIP100 disk size (as seen by akaiutil): 12288 blocks (8KB) = 98304KB = 96MB
|
||||||
|
|
||||||
|
ZIP250 disk size (as seen by akaiutil): 30595 blocks (8KB) = 244760KB = approx. 239MB
|
||||||
|
|
||||||
|
Warning: Formatting disk-files or floppies or physical drives destroys their contents!!! Use at your own risk!!!
|
||||||
|
|
||||||
|
Example 1: format S900 low-density (DD) floppy in floppy drive A: on Windows PC:
|
||||||
|
akaiutil.exe floppyla:
|
||||||
|
-> formatfloppyl9
|
||||||
|
|
||||||
|
Example 2: create and format S900 low-density floppy image
|
||||||
|
dd if=/dev/zero of=fff.img bs=1024 count=800
|
||||||
|
akaiutil fff.img
|
||||||
|
-> formatfloppyl9
|
||||||
|
|
||||||
|
Example 3: create and format S1000 high-density floppy image
|
||||||
|
dd if=/dev/zero of=fff.img bs=1024 count=1600
|
||||||
|
akaiutil fff.img
|
||||||
|
-> formatfloppyh1
|
||||||
|
|
||||||
|
Example 4: create and format CD3000 CD-ROM image of max. size
|
||||||
|
dd if=/dev/zero of=hhh.img bs=8192 count=65535
|
||||||
|
akaiutil hhh.img
|
||||||
|
-> formatharddisk3cd 60M
|
||||||
|
(this gives 8 partitions of 60MB and 1 partition of approx. 32MB)
|
||||||
|
-> setcdinfo MYCDROM
|
||||||
|
(this must be done after all volumes/files have been transferred)
|
||||||
|
|
||||||
|
Example 5: create and format S950 harddisk image of max. size
|
||||||
|
dd if=/dev/zero of=hhh.img bs=8192 count=8191
|
||||||
|
akaiutil hhh.img
|
||||||
|
-> formatharddisk9
|
||||||
|
|
||||||
|
Example 6: format ZIP100 drive at Windows physical drive 3 for S1000
|
||||||
|
akaiutil.exe -p 3
|
||||||
|
-> formatharddisk1 60M
|
||||||
|
(this gives 1 partition of 60MB and 1 partition of 36MB)
|
||||||
|
|
||||||
|
Example 7: format drive at Windows physical drive 4 for S1100 with DD space
|
||||||
|
akaiutil.exe -p 4
|
||||||
|
-> formatharddisk1 1M 1M
|
||||||
|
(this gives 1 partition of 1MB, rest of disk is allocated for DD)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Compilation:
|
||||||
|
------------
|
||||||
|
|
||||||
|
Depending on the operating system and the programming environment,
|
||||||
|
use Makefile (for make) or Makefile.nmake (for nmake) or the .vcproj file.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
References:
|
||||||
|
-----------
|
||||||
|
|
||||||
|
* documentation, manuals, and webpages for AKAI samplers
|
||||||
|
* floppies, harddisks, CD-ROMs, and files for AKAI samplers
|
||||||
|
* "AkaiDisk" and its documentation, by Paul Kellett, accessed 09-JAN-2008, 06-MAR-2008, 27-MAR-2010
|
||||||
|
* "akaitools", by Hiroyuki Ohsaki, accessed 09-JAN-2008
|
||||||
|
* "akaifs", by Raymond Dresens and Roger Karis, accessed 18-JAN-2008
|
||||||
|
* "libakai", by Sébastien Métrot and Christian Schoenebeck, accessed 09-JAN-2008
|
||||||
|
* "fdrawcmd.sys" by Simon Owen, https://simonowen.com/fdrawcmd/, accessed 14-AUG-2020
|
||||||
|
* "DiskUtil" by Simon Owen, https://simonowen.com/fdrawcmd/DiskUtil.zip, accessed 14-AUG-2020
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
The following holds for all files in this distribution (unless stated otherwise on an
|
||||||
|
individual basis for each file and statement):
|
||||||
|
|
||||||
|
These program/data/document/HTML/picture/media files (materials) are distributed in the
|
||||||
|
hope that they will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||||
|
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. In no event shall the author be
|
||||||
|
liable for any direct, indirect, incidental, special, exemplary, or consequential damages
|
||||||
|
(including, but not limited to, procurement of substitue goods or services; loss of use,
|
||||||
|
data, or profits; or business interruption) however caused and on any theory of liability,
|
||||||
|
whether in contract, strict liability, or tort (including negligence or otherwise) arising
|
||||||
|
in any way out of the use of data/information/software from this distribution, even if
|
||||||
|
advised of the possibility of such damage.
|
||||||
|
|
||||||
|
The contents of this distribution are intended for educational, non-commercial purposes
|
||||||
|
only. Materials contained herein are property of their respective owners.
|
||||||
|
All brand names and trademarks are property of their respective owners.
|
||||||
|
If any copyrighted works/trademarks have been used, please contact the author
|
||||||
|
and the item will be either removed or properly credited (at the copyright/trademark
|
||||||
|
owner's discretion). We have no intention of violating any copyrights or trademarks.
|
||||||
|
This distribution might use inlining and deep-linking, i.e. links in this distribution
|
||||||
|
might lead directly to materials on other web sites/distributions (in which case the
|
||||||
|
target page normally should be listed/credited in a "links" section). The author does
|
||||||
|
not take responsibility for the contents of any links referred to. We do not necessarily
|
||||||
|
endorse, sanction, support, encourage, verify or agree with the contents, opinions or
|
||||||
|
statements of/on any of the linked pages. These statements hold for all links/references
|
||||||
|
in all files in this distribution. We are in no way affiliated with any
|
||||||
|
companies/institutions/individuals which might be mentioned in any manner in this
|
||||||
|
distribution.
|
||||||
|
|
||||||
|
The author does not take responsibility for incorrect, incomplete or misleading information.
|
||||||
|
Statements are to be considered as the author's free personal opinion. The author does not
|
||||||
|
necessarly possess any of the items mentioned in files in this distribution.
|
||||||
|
|
||||||
|
Files (and the information therein) created by the author are copyright
|
||||||
|
(c) by the author. Unless protected/restricted otherwise, the author permits
|
||||||
|
reproduction/redistribution of material contained in this distribution under the condition
|
||||||
|
that the item is properly credited. Links to items/materials in this distribution are welcome.
|
||||||
|
Projects/publications/papers that make use of materials, programs, or generated output
|
||||||
|
of this distribution must properly credit the author and mention the usage of this distribution.
|
||||||
|
Please contact the author for comments or further questions
|
||||||
|
and permission to use materials/information from this distribution.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
This product includes software developed by the University of California, Berkeley
|
||||||
|
and its contributors.
|
||||||
|
|
||||||
|
Copyright (c) 1987-2002 The Regents of the University of California.
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. [rescinded 22 July 1999]
|
||||||
|
4. Neither the name of the University nor the names of its contributors
|
||||||
|
may be used to endorse or promote products derived from this software
|
||||||
|
without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
|
||||||
|
IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
|
||||||
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
End of file
|
||||||
+7254
File diff suppressed because it is too large
Load Diff
+674
@@ -0,0 +1,674 @@
|
|||||||
|
#ifndef __AKAIUTIL_H
|
||||||
|
#define __AKAIUTIL_H
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2008,2010,2012,2018,2019,2020,2021 Klaus Michael Indlekofer. All rights reserved.
|
||||||
|
*
|
||||||
|
* m.indlekofer@gmx.de
|
||||||
|
*
|
||||||
|
* This program 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 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include "commoninclude.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* AKAI S900/S1000/S3000 filesystems */
|
||||||
|
|
||||||
|
/* Note: all data types are little endian */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* floppy */
|
||||||
|
|
||||||
|
/* floppy filesystem blocksize */
|
||||||
|
#define AKAI_FL_BLOCKSIZE 0x0400 /* 1KB */
|
||||||
|
/* Note: must be == AKAI_FL_SECSIZE (low-level floppy sector size, defined in akaiutil_io.h) */
|
||||||
|
#if defined(AKAI_FL_SECSIZE)&&(AKAI_FL_BLOCKSIZE!=AKAI_FL_SECSIZE)
|
||||||
|
#error "AKAI_FL_BLOCKSIZE!=AKAI_FL_SECSIZE"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define AKAI_FLL_SIZE 0x0320 /* low-density floppy size in floppy blocks (800KB) */
|
||||||
|
#define AKAI_FLH_SIZE 0x0640 /* high-density floppy size in floppy blocks (1.6MB) */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* harddisk */
|
||||||
|
|
||||||
|
/* harddisk filesystem blocksize */
|
||||||
|
#define AKAI_HD_BLOCKSIZE 0x2000 /* 8KB */
|
||||||
|
|
||||||
|
/* S900 harddisk */
|
||||||
|
#define AKAI_HD9_MAXSIZE 0x1fff /* max. harddisk size in harddisk blocks (approx. 64MB) */
|
||||||
|
#define AKAI_HD9_DEFSIZE 0x09c4 /* default harddisk size in harddisk blocks (approx. 19.5MB) */
|
||||||
|
#define AKAI_HD9_SH205SIZE 0x0a29 /* "Atari SH205" harddisk size in harddisk blocks (approx. 20.3MB) */
|
||||||
|
#define AKAI_HD9_SUPRA20MSIZE 0x09c4 /* "Supra 20M" harddisk size in harddisk blocks (approx. 19.5MB) */
|
||||||
|
#define AKAI_HD9_SUPRA30MSIZE 0x0ee4 /* "Supra 30M" harddisk size in harddisk blocks (approx. 29.8MB) */
|
||||||
|
#define AKAI_HD9_SUPRA60MSIZE 0x1dc8 /* "Supra 60M" harddisk size in harddisk blocks (approx. 59.6MB) */
|
||||||
|
|
||||||
|
/* S1000/S3000 harddisk */
|
||||||
|
#define AKAI_HD_MAXSIZE 0xffff /* max. harddisk size in harddisk blocks (approx. 512MB, Note: for 16bit block numbers) */
|
||||||
|
|
||||||
|
/* S1000/S3000 harddisk sampler partition */
|
||||||
|
#define AKAI_PART_MAXSIZE 0x1e00 /* max. sampler partition size in harddisk blocks (60MB) */
|
||||||
|
#define AKAI_PART_NUM 18 /* max. number of sampler partitions per harddisk */
|
||||||
|
|
||||||
|
/* S1100/S3000 harddisk DD partition */
|
||||||
|
/* Note: max. DD partition size in harddisk blocks is AKAI_HD_MAXSIZE */
|
||||||
|
#define AKAI_DDPART_CBLKS 0x20 /* number of blocks per DD partition cluster */
|
||||||
|
#define AKAI_DDPART_NUM 18 /* max. number of DD partitions per harddisk */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* max. disk size in bytes, Note: fits into 32bit */
|
||||||
|
#define AKAI_DISKSIZE_MAX (AKAI_HD_MAXSIZE*AKAI_HD_BLOCKSIZE)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* names */
|
||||||
|
|
||||||
|
#define AKAI_NAME_LEN_S900 10 /* for S900 */
|
||||||
|
#define AKAI_NAME_LEN 12 /* for S1000/S3000 */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* FAT (for floppies and harddisk sampler partitions) */
|
||||||
|
|
||||||
|
#define AKAI_FAT_CODE_FREE 0x0000 /* free block */
|
||||||
|
#define AKAI_FAT_CODE_BAD 0x2000 /* bad block */
|
||||||
|
#define AKAI_FAT_CODE_SYS900FL 0x0000 /* block reserved for system (S900 floppy), warning: same as for free block!!! */
|
||||||
|
#define AKAI_FAT_CODE_SYS900HD 0xffff /* block reserved for system (S900 harddisk) */
|
||||||
|
#define AKAI_FAT_CODE_SYS 0x4000 /* block reserved for system (S1000/S3000) */
|
||||||
|
#define AKAI_FAT_CODE_DIREND900HD 0x8000 /* end of chain for volume directory (S900 harddisk) */
|
||||||
|
#define AKAI_FAT_CODE_DIREND1000HD 0x4000 /* end of chain for volume directory (S1000 harddisk), warning: same as for system block!!! */
|
||||||
|
#define AKAI_FAT_CODE_DIREND3000 0x8000 /* end of chain for volume directory (S3000) */
|
||||||
|
#define AKAI_FAT_CODE_FILEEND900 0x8000 /* end of chain for file (S900) */
|
||||||
|
#define AKAI_FAT_CODE_FILEEND 0xc000 /* end of chain for file (S1000/S3000) */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* DD FAT (for S1100/S3000 harddisk DD partition) */
|
||||||
|
|
||||||
|
#define AKAI_DDFAT_CODE_FREE 0x0000 /* free cluster */
|
||||||
|
#define AKAI_DDFAT_CODE_BAD 0x2000 /* bad cluster */
|
||||||
|
#define AKAI_DDFAT_CODE_SYS 0x8000 /* cluster reserved for system (header cluster) */
|
||||||
|
#define AKAI_DDFAT_CODE_END 0xffff /* end of chain */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* OS versions for volumes and files */
|
||||||
|
|
||||||
|
#define AKAI_OSVER_S900VOL 0x0000 /* OS version of S900/S950 volume (zero) */
|
||||||
|
#define AKAI_OSVER_S1000MAX 0x0428 /* max. OS version of S1000 ("4.40") */
|
||||||
|
#define AKAI_OSVER_S1100MAX 0x091e /* max. OS version of S1100 ("9.30") */
|
||||||
|
#define AKAI_OSVER_S3000MAX 0x1100 /* max. OS version of S3000 ("17.00") */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* file */
|
||||||
|
|
||||||
|
#define AKAI_FILE_SIZEMAX 0xffffff /* max. file size in bytes (approx. 16MB, Note: for 24bit size in volume directory entry for file) */
|
||||||
|
|
||||||
|
/* entry in volume directory for file */
|
||||||
|
struct akai_voldir_entry_s{
|
||||||
|
/* Note: S900 uses first AKAI_NAME_LEN900 chars in name, rest is zero */
|
||||||
|
u_char name[AKAI_NAME_LEN]; /* file name */
|
||||||
|
#define AKAI_FILE_TAGNUM 0x04 /* number of tags in volume directory entry for file */
|
||||||
|
#define AKAI_FILE_TAGFREE 0x00 /* invalid tag number, means: free tag entry for S3000 */
|
||||||
|
#define AKAI_FILE_TAGS1000 0x20 /* invalid tag number, default for S1000 */
|
||||||
|
/* Note: valid tag numbers are 1, ..., AKAI_PARTHEAD_TAGNUM */
|
||||||
|
/* Note: S900 has no tags, all zero */
|
||||||
|
u_char tag[AKAI_FILE_TAGNUM]; /* tags */
|
||||||
|
#define AKAI_FTYPE_FREE 0x00 /* invalid file type, means: free entry in volume directory */
|
||||||
|
u_char type; /* file type */
|
||||||
|
u_char size[3]; /* file size in bytes (Note: 24bit) */
|
||||||
|
u_char start[2]; /* start block within partition */
|
||||||
|
u_char osver[2]; /* if S1000/S3000: OS version */
|
||||||
|
/* if S900 compressed file: number of un-compressed floppy blocks */
|
||||||
|
/* else: zero */
|
||||||
|
}; /* Note: should be 0x0018 Bytes */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* volume parameters */
|
||||||
|
/* Note: S900 has no volume parameters */
|
||||||
|
struct akai_volparam_s{
|
||||||
|
u_char progselmidich1; /* program select MIDI channel-1 */
|
||||||
|
u_char progselomni; /* MIDI OMNI for program select */
|
||||||
|
u_char progselenab; /* program select enable */
|
||||||
|
u_char prognr1; /* selected program number-1 */
|
||||||
|
u_char playinominovrr; /* MIDI OMNI override for play input */
|
||||||
|
u_char sysexch1; /* MIDI system exclusive channel-1 */
|
||||||
|
u_char dummy1[42]; /* XXX */
|
||||||
|
}; /* Note: should be 0x0030 Bytes */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* harddisk volumes */
|
||||||
|
|
||||||
|
/* harddisk volume directory of files */
|
||||||
|
#define AKAI_VOLDIR_ENTRIES_S900HD 128 /* total number of volume directory entries for S900 */
|
||||||
|
#define AKAI_VOLDIR_ENTRIES_S1000HD 126 /* total number of volume directory entries for S1000 */
|
||||||
|
#define AKAI_VOLDIR_ENTRIES_S3000HD 510 /* total number of volume directory entries for S3000 */
|
||||||
|
#define AKAI_VOLDIR_ENTRIES_1BLKHD 341 /* max. number of volume directory entries in 1 harddisk block */
|
||||||
|
|
||||||
|
/* S900 harddisk volume */
|
||||||
|
struct akai_voldir900hd_s{
|
||||||
|
struct akai_voldir_entry_s file[AKAI_VOLDIR_ENTRIES_S900HD]; /* volume directory entries for files */
|
||||||
|
u_char dummy1[0x1400]; /* XXX */
|
||||||
|
}; /* Note: should be 1 harddisk block */
|
||||||
|
#define AKAI_VOLDIR900HD_BLKS 1
|
||||||
|
|
||||||
|
/* S1000 harddisk volume */
|
||||||
|
struct akai_voldir1000hd_s{
|
||||||
|
struct akai_voldir_entry_s file[AKAI_VOLDIR_ENTRIES_S1000HD]; /* volume directory entries for files */
|
||||||
|
struct akai_volparam_s param; /* volume parameters */
|
||||||
|
u_char dummy1[0x1400]; /* XXX */
|
||||||
|
}; /* Note: should be 1 harddisk block */
|
||||||
|
#define AKAI_VOLDIR1000HD_BLKS 1
|
||||||
|
|
||||||
|
/* S3000 harddisk volume */
|
||||||
|
struct akai_voldir3000hd_s{
|
||||||
|
struct akai_voldir_entry_s file[AKAI_VOLDIR_ENTRIES_S3000HD]; /* volume directory entries for files */
|
||||||
|
struct akai_volparam_s param; /* volume parameters */
|
||||||
|
u_char dummy1[0x1000]; /* XXX */
|
||||||
|
}; /* Note: should be 2 harddisk blocks */
|
||||||
|
#define AKAI_VOLDIR3000HD_BLKS 2
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* floppy volumes */
|
||||||
|
|
||||||
|
/* floppy volume directory of files */
|
||||||
|
#define AKAI_VOLDIR_ENTRIES_S1000FL 64 /* number of volume directory entries total for S900 and S1000 floppy */
|
||||||
|
#define AKAI_VOLDIR_ENTRIES_S3000FL 510 /* number of volume directory entries total for S3000 floppy */
|
||||||
|
|
||||||
|
/* floppy volume label */
|
||||||
|
/* Note: S900 has no floppy volume label, all zero */
|
||||||
|
struct akai_flvol_label_s{
|
||||||
|
u_char name[AKAI_NAME_LEN]; /* volume name */
|
||||||
|
u_char dummy1[2]; /* XXX */
|
||||||
|
u_char osver[2]; /* OS version */
|
||||||
|
struct akai_volparam_s param; /* volume parameters */
|
||||||
|
}; /* Note: should be 0x0040 Bytes */
|
||||||
|
|
||||||
|
/* low-density floppy header */
|
||||||
|
/* Note: S900 and S1000 floppy volume directory is within floppy header */
|
||||||
|
struct akai_fllhead_s{
|
||||||
|
struct akai_voldir_entry_s file[AKAI_VOLDIR_ENTRIES_S1000FL]; /* volume directory entries for files */
|
||||||
|
#define AKAI_FAT_ENTRIES_FLL AKAI_FLL_SIZE /* number of FAT entries */
|
||||||
|
u_char fatblk[AKAI_FAT_ENTRIES_FLL][2]; /* FAT entries for floppy blocks: next block or special code */
|
||||||
|
/* Note: S900 has no floppy volume label, all zero */
|
||||||
|
struct akai_flvol_label_s label; /* label */
|
||||||
|
u_char dummy1[0x0380]; /* XXX */
|
||||||
|
}; /* Note: should be 4 floppy blocks */
|
||||||
|
#define AKAI_FLLHEAD_BLKS 4
|
||||||
|
|
||||||
|
/* high-density floppy header */
|
||||||
|
/* Note: S900 and S1000 floppy volume directory is within floppy header */
|
||||||
|
/* Note: low- and high-density floppy headers are identical */
|
||||||
|
/* up to first AKAI_FAT_ENTRIES_FLL FAT-entries */
|
||||||
|
struct akai_flhhead_s{
|
||||||
|
struct akai_voldir_entry_s file[AKAI_VOLDIR_ENTRIES_S1000FL]; /* volume directory entries for files */
|
||||||
|
#define AKAI_FAT_ENTRIES_FLH AKAI_FLH_SIZE /* number of FAT entries */
|
||||||
|
u_char fatblk[AKAI_FAT_ENTRIES_FLH][2]; /* FAT entries for floppy blocks: next block or special code */
|
||||||
|
/* Note: S900 has no floppy volume label, all zero */
|
||||||
|
struct akai_flvol_label_s label; /* label */
|
||||||
|
u_char dummy1[0x0140]; /* XXX */
|
||||||
|
}; /* Note: should be 5 floppy blocks */
|
||||||
|
#define AKAI_FLHHEAD_BLKS 5
|
||||||
|
|
||||||
|
/* S3000 floppy volume directory (behind header) */
|
||||||
|
struct akai_voldir3000fl_s{
|
||||||
|
struct akai_voldir_entry_s file[AKAI_VOLDIR_ENTRIES_S3000FL]; /* volume directory entries for files */
|
||||||
|
u_char dummy1[0x0030]; /* Note: volume parameters are in floppy header */
|
||||||
|
}; /* Note: should be 12 floppy blocks */
|
||||||
|
#define AKAI_VOLDIR3000FL_BLKS 12
|
||||||
|
#define AKAI_VOLDIR3000FLL_BSTART 4 /* start block for low-density */
|
||||||
|
#define AKAI_VOLDIR3000FLH_BSTART 5 /* start block for high-density */
|
||||||
|
/* flag for S3000 floppy: invalid type of first file in floppy header */
|
||||||
|
#define AKAI_VOLDIR3000FL_FTYPE 0xff /* invalid file type, used as flag for S3000 floppy volume */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* generic volume */
|
||||||
|
/* Note: first file starts at byte 0 in first block */
|
||||||
|
union akai_voldir_u{
|
||||||
|
struct akai_voldir900hd_s s900hd;
|
||||||
|
struct akai_voldir1000hd_s s1000hd;
|
||||||
|
struct akai_voldir3000hd_s s3000hd;
|
||||||
|
/* Note: S900 and S1000 floppy volume is within floppy header */
|
||||||
|
struct akai_voldir3000fl_s s3000fl;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* entry in root directory for volume on S900 harddisk */
|
||||||
|
struct akai_hd9rootdir_entry_s{
|
||||||
|
u_char name[AKAI_NAME_LEN_S900]; /* volume name */
|
||||||
|
#define AKAI_VOL_START_INACT 0x0000 /* inactive */
|
||||||
|
u_char start[2]; /* start block on harddisk */
|
||||||
|
}; /* Note: should be 0x000c Bytes */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* S900 harddisk header */
|
||||||
|
struct akai_hd9head_s{
|
||||||
|
#define AKAI_HD9ROOTDIR_ENTRIES 128 /* number of root directory entries for volumes */
|
||||||
|
struct akai_hd9rootdir_entry_s vol[AKAI_HD9ROOTDIR_ENTRIES]; /* root directory for volumes */
|
||||||
|
u_char size[2]; /* harddisk size in harddisk blocks */
|
||||||
|
#define AKAI_HD9FLAG1_SIZEVALID 0xff /* if size[] is valid */
|
||||||
|
u_char flag1; /* XXX */
|
||||||
|
u_char flag2; /* XXX */
|
||||||
|
#define AKAI_HD9FAT0_ENTRIES 0x0cfe /* number of copied FAT entries */
|
||||||
|
u_char fatblk0[AKAI_HD9FAT0_ENTRIES][2]; /* copy of first FAT entries */
|
||||||
|
#define AKAI_HD9FAT_ENTRIES AKAI_HD9_MAXSIZE /* max. number of FAT entries */
|
||||||
|
u_char fatblk[AKAI_HD9FAT_ENTRIES][2]; /* FAT entries for harddisk blocks: next block or special code */
|
||||||
|
u_char dummy1[0x6000-AKAI_HD9FAT_ENTRIES*2]; /* XXX */
|
||||||
|
}; /* Note: should be 4 harddisk blocks */
|
||||||
|
#define AKAI_HD9HEAD_BLKS 4
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* entry in root directory for volume in S1000/S3000 harddisk sampler partition */
|
||||||
|
struct akai_rootdir_entry_s{
|
||||||
|
u_char name[AKAI_NAME_LEN]; /* volume name */
|
||||||
|
#define AKAI_VOL_TYPE_INACT 0x00 /* inactive */
|
||||||
|
#define AKAI_VOL_TYPE_S1000 0x01 /* S1000 */
|
||||||
|
#define AKAI_VOL_TYPE_S3000 0x03 /* S3000 or CD3000 */
|
||||||
|
#define AKAI_VOL_TYPE_CD3000 0x07 /* CD3000 CD-ROM (compatible with AKAI_VOL_TYPE_S3000) */
|
||||||
|
u_char type; /* volume type */
|
||||||
|
#define AKAI_VOL_LNUM_OFF 0
|
||||||
|
#define AKAI_VOL_LNUM_MIN 1
|
||||||
|
#define AKAI_VOL_LNUM_MAX 128
|
||||||
|
u_char lnum; /* load number */
|
||||||
|
u_char start[2]; /* start block within partition */
|
||||||
|
}; /* Note: should be 0x0010 Bytes */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* S1000/S3000 harddisk sampler and DD partition table (only in first sampler partition) */
|
||||||
|
struct akai_parttab_s{
|
||||||
|
#define AKAI_PARTTAB_MAGICNUM 128 /* number of fields */
|
||||||
|
#define AKAI_PARTTAB_MAGICVAL 9999 /* magic base value */
|
||||||
|
u_char magic[AKAI_PARTTAB_MAGICNUM][2]; /* magic fields, indicate S1000/S3000 harddisk partition table, only in first sampler partition */
|
||||||
|
u_char partnum; /* number of sampler partitions, only in first sampler partition */
|
||||||
|
u_char ddpartnum; /* number of DD partitions */
|
||||||
|
u_char part[AKAI_PART_NUM+1][2]; /* sampler partition table, only in first sampler partition */
|
||||||
|
u_char ddpart[AKAI_DDPART_NUM+1][2]; /* DD partition table, only in first sampler partition */
|
||||||
|
u_char dummy1[0x0100-2-2*(AKAI_PART_NUM+1)-2*(AKAI_DDPART_NUM+1)]; /* XXX */
|
||||||
|
}; /* Note: should be 0x0202 Bytes */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* S1000/S3000 harddisk sampler partition header */
|
||||||
|
struct akai_parthead_s{
|
||||||
|
u_char size[2]; /* partition size in harddisk blocks */
|
||||||
|
#define AKAI_PARTHEAD_MAGICNUM 98 /* number of fields */
|
||||||
|
#define AKAI_PARTHEAD_MAGICVAL 3333 /* magic base value */
|
||||||
|
u_char magic[AKAI_PARTHEAD_MAGICNUM][2]; /* magic fields, indicate S1000/S3000 harddisk sampler partition */
|
||||||
|
u_char chksum[4]; /* checksum of all above */
|
||||||
|
#define AKAI_ROOTDIR_ENTRIES 100 /* number of root directory entries for volumes */
|
||||||
|
struct akai_rootdir_entry_s vol[AKAI_ROOTDIR_ENTRIES]; /* root directory for volumes */
|
||||||
|
#define AKAI_FAT_ENTRIES AKAI_PART_MAXSIZE /* max. number of FAT entries */
|
||||||
|
u_char fatblk[AKAI_FAT_ENTRIES][2]; /* FAT entries for sampler partition blocks: next block or special code */
|
||||||
|
u_char dummy1[0x00f6]; /* XXX */
|
||||||
|
struct akai_parttab_s parttab; /* partition table, only in first sampler partition */
|
||||||
|
#define AKAI_PARTHEAD_TAGSMAGIC "TAGS" /* magic for tags */
|
||||||
|
u_char tagsmagic[4]; /* magic for tags */
|
||||||
|
#define AKAI_PARTHEAD_TAGNUM 26 /* number of tags */
|
||||||
|
u_char tag[AKAI_PARTHEAD_TAGNUM][AKAI_NAME_LEN]; /* tag names */
|
||||||
|
u_char dummy2[0x1a00-4-AKAI_PARTHEAD_TAGNUM*AKAI_NAME_LEN]; /* XXX */
|
||||||
|
}; /* Note: should be 3 harddisk blocks */
|
||||||
|
#define AKAI_PARTHEAD_BLKS 3
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* S1100/S3000 DD take header (directory entry in DD partition header) */
|
||||||
|
/* XXX should be defined in akaiutil_take.h, but must be in akaiutil.h due to dependencies */
|
||||||
|
struct akai_ddtake_s{
|
||||||
|
u_char name[AKAI_NAME_LEN]; /* name */
|
||||||
|
u_char cstarts[2]; /* start cluster for sample */
|
||||||
|
u_char cstarte[2]; /* start cluster for envelope */
|
||||||
|
u_char wstart[4]; /* sample start word (16bit) */
|
||||||
|
u_char wend[4]; /* sample end word (16bit) */
|
||||||
|
#define AKAI_DDTAKESTAT_FREE 0x00 /* free directory entry */
|
||||||
|
#define AKAI_DDTAKESTAT_USED 0x01 /* used directory entry */
|
||||||
|
u_char stat; /* directory entry status */
|
||||||
|
#define AKAI_DDTAKESTYPE_MONO 0x00 /* sample type mono */
|
||||||
|
#define AKAI_DDTAKESTYPE_STEREO 0x01 /* sample type stereo */
|
||||||
|
u_char stype; /* sample type */
|
||||||
|
u_char srate[2]; /* sample rate in Hz */
|
||||||
|
u_char vspeed[2]; /* varispeed (signed) */
|
||||||
|
u_char finerate[2]; /* fine rate (signed) */
|
||||||
|
u_char wstartm[4]; /* edit marker sample start word (16bit) */
|
||||||
|
u_char wendm[4]; /* edit marker sample end word (16bit) */
|
||||||
|
u_char fadein[2]; /* fade in time in ms */
|
||||||
|
u_char fadeout[2]; /* fade out time in ms */
|
||||||
|
u_char stlvl; /* stereo output level */
|
||||||
|
u_char pan; /* panning (signed) */
|
||||||
|
u_char stmix; /* stereo mix (ON=0x01, OFF=0x00) */
|
||||||
|
u_char midich1; /* MIDI channel-1 */
|
||||||
|
u_char midinote; /* MIDI note */
|
||||||
|
u_char startm; /* start mode */
|
||||||
|
u_char deemph; /* de-emphasis (ON=0x01, OFF=0x00) */
|
||||||
|
u_char dummy1[5]; /* XXX */
|
||||||
|
u_char predel[2]; /* pre-delay time in ms */
|
||||||
|
u_char outlvl; /* output level */
|
||||||
|
u_char outch; /* output channel pair */
|
||||||
|
u_char fxbus; /* FX bus */
|
||||||
|
u_char sendlvl; /* send level */
|
||||||
|
u_char dummy2[2]; /* XXX */
|
||||||
|
}; /* Note: should be 0x0040 Bytes */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* S1100/S3000 harddisk DD partition header */
|
||||||
|
struct akai_ddparthead_s{
|
||||||
|
#define AKAI_DDFAT_ENTRIES 0x07ff /* max. number of DD FAT entries (AKAI_HD_MAXSIZE/AKAI_DDPART_CBLKS) */
|
||||||
|
u_char fatcl[AKAI_DDFAT_ENTRIES][2]; /* FAT entries for DD partition clusters: next cluster or special code */
|
||||||
|
u_char dummy1[0x2000-AKAI_DDFAT_ENTRIES*2]; /* XXX */
|
||||||
|
#define AKAI_DDTAKE_MAXNUM 256 /* max. number of DD takes */
|
||||||
|
struct akai_ddtake_s take[AKAI_DDTAKE_MAXNUM]; /* directory of DD takes */
|
||||||
|
}; /* Note: should be 3 harddisk blocks (rest of cluster is junk) */
|
||||||
|
#define AKAI_DDPARTHEAD_BLKS 3
|
||||||
|
|
||||||
|
#define AKAI_DDTAKE_ENVBLKSIZW 128 /* envelope block size in words */
|
||||||
|
#define AKAI_DDTAKE_ENVMAXVAL 0x20 /* max. envelope value */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* generic header */
|
||||||
|
union akai_head_u{
|
||||||
|
struct akai_fllhead_s fll; /* low-density floppy header */
|
||||||
|
struct akai_flhhead_s flh; /* high-density floppy header */
|
||||||
|
struct akai_hd9head_s hd9; /* S900 harddisk header */
|
||||||
|
struct akai_parthead_s hd; /* S1000/S3000 harddisk sampler partition header */
|
||||||
|
struct akai_ddparthead_s dd; /* S1000/S3000 harddisk DD partition header */
|
||||||
|
};
|
||||||
|
/* Note: see comment above: */
|
||||||
|
/* may access files and first blocks in FAT via */
|
||||||
|
/* high-density floppy header also for low-density floppy case */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* CD-ROM info header in S1000/S3000 sampler partition */
|
||||||
|
struct akai_cdinfohead_s{
|
||||||
|
u_char fnum[2]; /* number of files */
|
||||||
|
u_char volesiz[AKAI_ROOTDIR_ENTRIES][2]; /* size of volume directory entries for files in bytes */
|
||||||
|
u_char cdlabel[AKAI_NAME_LEN]; /* CD-ROM label */
|
||||||
|
}; /* Note: should be 0x00d6 Bytes */
|
||||||
|
/* Note: followed by voldir entries of files */
|
||||||
|
#define AKAI_CDINFO_BLK AKAI_PARTHEAD_BLKS /* start block (following sampler partition header) */
|
||||||
|
#define AKAI_CDINFO_MINSIZB 3 /* min. size in harddisk blocks */
|
||||||
|
#define AKAI_CDINFO_DEFLABEL "CDROM" /* XXX default label */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* private data structures */
|
||||||
|
|
||||||
|
/* disk */
|
||||||
|
struct disk_s{
|
||||||
|
u_int index; /* disk index */
|
||||||
|
int fd; /* disk file descriptor */
|
||||||
|
#ifdef _VISUALCPP
|
||||||
|
int fldrn; /* floppy drive number (or -1 if none) */
|
||||||
|
#endif /* _VISUALCPP */
|
||||||
|
int readonly; /* read-only flag */
|
||||||
|
OFF64_T startoff; /* start offset in bytes */
|
||||||
|
u_int totsize; /* size in bytes */
|
||||||
|
#define DISK_TYPE_FLL 1 /* low-density floppy */
|
||||||
|
#define DISK_TYPE_FLH 2 /* high-density floppy */
|
||||||
|
#define DISK_TYPE_HD9 9 /* S900 harddisk */
|
||||||
|
#define DISK_TYPE_HD 3 /* S1000/S3000 harddisk */
|
||||||
|
u_int type; /* disk type */
|
||||||
|
u_int blksize; /* blocksize in bytes */
|
||||||
|
u_int bsize; /* size in blocks */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* partition */
|
||||||
|
struct part_s{
|
||||||
|
struct disk_s *diskp; /* pointer to disk */
|
||||||
|
int valid; /* check passed */
|
||||||
|
#define PART_TYPE_FLL DISK_TYPE_FLL /* low-density floppy */
|
||||||
|
#define PART_TYPE_FLH DISK_TYPE_FLH /* high-density floppy */
|
||||||
|
#define PART_TYPE_HD9 DISK_TYPE_HD9 /* S900 harddisk */
|
||||||
|
#define PART_TYPE_HD DISK_TYPE_HD /* S1000/S3000 harddisk sampler partition */
|
||||||
|
#define PART_TYPE_DD 4 /* S1100/S3000 harddisk DD partition (at end of harddisk) */
|
||||||
|
u_int type; /* partition type */
|
||||||
|
u_int index; /* index on disk */
|
||||||
|
u_int blksize; /* blocksize in bytes */
|
||||||
|
u_int bstart; /* start block on disk */
|
||||||
|
u_int bsize; /* size in blocks */
|
||||||
|
u_int csize; /* if DD partition: size in clusters */
|
||||||
|
u_int bsyssize; /* if not DD partition: reserved blocks for system (partition header or floppy header) */
|
||||||
|
u_int bfree; /* free blocks */
|
||||||
|
u_int bbad; /* bad blocks */
|
||||||
|
u_char (*fat)[2]; /* start of FAT */
|
||||||
|
union akai_head_u head; /* whole header */
|
||||||
|
u_int volnummax; /* if not DD partition: max. number of volumes */
|
||||||
|
char letter; /* letter (ASCII) */
|
||||||
|
};
|
||||||
|
/* Note: fat points into original part_s head => must not use(!) a copy of a part_s !!! */
|
||||||
|
|
||||||
|
/* volume */
|
||||||
|
struct vol_s{
|
||||||
|
struct part_s *partp; /* pointer to partition */
|
||||||
|
u_int index; /* index in root directory */
|
||||||
|
#define AKAI_VOL_TYPE_S900 0xf9 /* fake type for S900, not valid for type in S1000/S3000 root directory */
|
||||||
|
u_int type; /* volume type */
|
||||||
|
u_int lnum; /* load number */
|
||||||
|
u_int osver; /* OS version */
|
||||||
|
#define VOL_DIRBLKS AKAI_VOLDIR3000FL_BLKS /* XXX max. number of volume blocks */
|
||||||
|
u_int dirblk[VOL_DIRBLKS]; /* directory blocks */
|
||||||
|
u_int fimax; /* max. file entries */
|
||||||
|
struct akai_voldir_entry_s *file; /* pointer to start of files */
|
||||||
|
struct akai_volparam_s *param; /* pointer to volume parameters */
|
||||||
|
union akai_voldir_u dir; /* whole volume directory (except for S900 and S1000 floppy) */
|
||||||
|
char name[AKAI_NAME_LEN+1]; /* name (ASCII), +1 for '\0' */
|
||||||
|
};
|
||||||
|
/* Note: file, param point into original vol_s dir => must not use(!) a copy of a vol_s !!! */
|
||||||
|
/* => use akai_copy_vol() to obtain a self-contained copy of a vol_s */
|
||||||
|
/* Note: must be careful with partp if part_s behind it has changed/disappeared !!! */
|
||||||
|
/* this should never be a problem since system-wide unique and static part[] */
|
||||||
|
|
||||||
|
/* sampler file */
|
||||||
|
struct file_s{
|
||||||
|
struct vol_s *volp; /* pointer to volume */
|
||||||
|
u_int index; /* index in volume directory */
|
||||||
|
u_int bstart; /* start block */
|
||||||
|
u_int size; /* size in bytes */
|
||||||
|
u_int type; /* type */
|
||||||
|
u_int osver; /* OS version */
|
||||||
|
u_char tag[AKAI_FILE_TAGNUM]; /* tags */
|
||||||
|
char name[AKAI_NAME_LEN+4+1]; /* name (ASCII), +4 for ".<type>", +1 for '\0' */
|
||||||
|
};
|
||||||
|
/* Note: must be careful with volp if vol_s behind it has changed/disappeared !!! */
|
||||||
|
/* this could be a problem with non-unique curvolp/curvol_buf */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* disks */
|
||||||
|
#ifndef DISK_NUM_MAX
|
||||||
|
#define DISK_NUM_MAX 64 /* XXX */
|
||||||
|
#endif
|
||||||
|
extern struct disk_s disk[DISK_NUM_MAX]; /* disks, Note: one for each disk, system-wide */
|
||||||
|
extern u_int disk_num; /* number of disks */
|
||||||
|
|
||||||
|
/* partitions */
|
||||||
|
#ifndef PART_NUM_MAX
|
||||||
|
#define PART_NUM_MAX 512 /* XXX */
|
||||||
|
#endif
|
||||||
|
extern struct part_s part[PART_NUM_MAX]; /* partitions, Note: one for each partition, system-wide */
|
||||||
|
extern u_int part_num; /* number of partitions */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* current directory */
|
||||||
|
extern struct disk_s *curdiskp; /* current disk pointer into disk[], NULL if system-level */
|
||||||
|
/* Note: unique, fixed mapping to each file */
|
||||||
|
extern struct part_s *curpartp; /* current partition pointer into part[], NULL if disk-level */
|
||||||
|
/* Note: unique, fixed mapping to each partition */
|
||||||
|
extern struct vol_s *curvolp; /* current volume pointer into curvol_buf, NULL if disk- or partition-level */
|
||||||
|
/* Note: neither fixed nor unique mapping to each volume!!! */
|
||||||
|
extern struct vol_s curvol_buf; /* current volume buffer, Note: only one buffer, might change volume identity!!! */
|
||||||
|
|
||||||
|
/* for operations with current directory, Note: one instance only, not recursive!!! */
|
||||||
|
extern int savecurfd;
|
||||||
|
extern struct part_s *savecurpartp;
|
||||||
|
extern struct vol_s *savecurvolp;
|
||||||
|
extern struct vol_s savecurvol_buf;
|
||||||
|
extern int savecurvolmodflag; /* modifier flag */
|
||||||
|
extern char savecurvolname[AKAI_NAME_LEN+1]; /* +1 for '\0' */
|
||||||
|
|
||||||
|
/* Note: dirnamebuf[] must be large enough to contain path of max. possible size */
|
||||||
|
#define DIRNAMEBUF_LEN 256 /* XXX */
|
||||||
|
extern char dirnamebuf[DIRNAMEBUF_LEN+1]; /* +1 for '\0' */
|
||||||
|
|
||||||
|
extern u_char curfiltertag[AKAI_FILE_TAGNUM];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Declarations */
|
||||||
|
|
||||||
|
#ifndef PSEUDODISK_NUM_MAX
|
||||||
|
#define PSEUDODISK_NUM_MAX 8 /* XXX max. number of pseudo-disks per file descriptor */
|
||||||
|
#endif
|
||||||
|
extern int open_disk(char *name,int readonly,OFF64_T startoff,u_int pseudodisksize,u_int pseudodisknum);
|
||||||
|
extern void close_alldisks(void);
|
||||||
|
|
||||||
|
#ifndef AKAI_DISKSIZE_GRAN
|
||||||
|
#define AKAI_DISKSIZE_GRAN 2048 /* XXX disk size granularity in bytes, compatible with CD-ROM */
|
||||||
|
#endif
|
||||||
|
extern u_int akai_disksize(int fd,OFF64_T startoff,u_int disksizemax);
|
||||||
|
|
||||||
|
extern int akai_io_blks(struct part_s *pp,u_char *buf,u_int bstart,u_int bsize,int cachealloc,int mode);
|
||||||
|
|
||||||
|
extern int akai_openreadonly_extfile(char *name);
|
||||||
|
extern int akai_check_extwavname(char *wavname);
|
||||||
|
|
||||||
|
extern void akai_countfree_part(struct part_s *pp);
|
||||||
|
extern int akai_check_fatblk(u_int blk,u_int bsize,u_int bsyssize);
|
||||||
|
extern int print_fatchain(struct part_s *pp,u_int blk);
|
||||||
|
extern int akai_free_fatchain(struct part_s *pp,u_int bstart,int writeflag);
|
||||||
|
extern int akai_allocate_fatchain(struct part_s *pp,u_int bsize,u_int *bstartp,u_int bcont0,u_int endcode);
|
||||||
|
|
||||||
|
extern int akai_scanbad(struct part_s *pp,int markflag);
|
||||||
|
|
||||||
|
extern int akai_read_file(int outfd,u_char *outbuf,struct file_s *fp,u_int begin,u_int end);
|
||||||
|
extern int akai_write_file(int inpfd,u_char *inpbuf,struct file_s *fp,u_int begin,u_int end);
|
||||||
|
|
||||||
|
extern int print_ddfatchain(struct part_s *pp,u_int cstart);
|
||||||
|
extern u_int akai_count_ddfatchain(struct part_s *pp,u_int cstart);
|
||||||
|
extern int akai_free_ddfatchain(struct part_s *pp,u_int cstart,int writeflag);
|
||||||
|
extern int akai_allocate_ddfatchain(struct part_s *pp,u_int csize,u_int *cstartp,u_int ccont0);
|
||||||
|
|
||||||
|
extern int akai_export_ddfatchain(struct part_s *pp,u_int cstart,u_int bstart,u_int bsize,int outfd,u_char *outbuf);
|
||||||
|
extern int akai_import_ddfatchain(struct part_s *pp,u_int cstart,u_int bstart,u_int bsize,int inpfd,u_char *inpbuf);
|
||||||
|
|
||||||
|
extern char akai2ascii(u_char c);
|
||||||
|
extern char akai2ascii900(u_char c);
|
||||||
|
extern void akai2ascii_name(u_char *aname,char *name,int s900flag);
|
||||||
|
extern void akai2ascii_filename(u_char *aname,u_char ft,u_int osver,char *name,int s900flag);
|
||||||
|
extern u_char ascii2akai(char a);
|
||||||
|
extern u_char ascii2akai900(char a);
|
||||||
|
extern void ascii2akai_name(char *name,u_char *aname,int s900flag);
|
||||||
|
extern u_char ascii2akai_filename(char *name,u_char *aname,u_int *osverp,int s900flag);
|
||||||
|
|
||||||
|
extern void akai_vol_info(struct vol_s *vp,u_int ai,int verbose);
|
||||||
|
extern void akai_list_vol(struct vol_s *vp,u_char *filtertagp);
|
||||||
|
extern int akai_read_voldir(struct vol_s *vp);
|
||||||
|
extern int akai_write_voldir(struct vol_s *vp,u_int fi);
|
||||||
|
extern void akai_copy_structvol(struct vol_s *srcvp,struct vol_s *dstvp);
|
||||||
|
extern int akai_get_vol(struct part_s *pp,struct vol_s *vp,u_int vi);
|
||||||
|
extern int akai_find_vol(struct part_s *pp,struct vol_s *vp,char *name);
|
||||||
|
extern int akai_rename_vol(struct vol_s *vp,char *name,u_int lnum,u_int osver,struct akai_volparam_s *parp);
|
||||||
|
#define AKAI_CREATE_VOL_NOINDEX ((u_int)-1) /* no user-supplied index */
|
||||||
|
extern int akai_create_vol(struct part_s *pp,struct vol_s *vp,u_int type,u_int index,char *name,u_int lnum,struct akai_volparam_s *parp);
|
||||||
|
extern int akai_wipe_vol(struct vol_s *vp,int delflag);
|
||||||
|
|
||||||
|
extern void akai_list_volparam(struct akai_volparam_s *parp,int listflag);
|
||||||
|
extern void akai_init_volparam(struct akai_volparam_s *parp,int s3000flag);
|
||||||
|
|
||||||
|
extern void akai_print_lnum(u_int lnum);
|
||||||
|
extern u_int akai_get_lnum(char *name);
|
||||||
|
|
||||||
|
extern int copy_tags(struct part_s *srcpp,struct part_s *dstpp);
|
||||||
|
extern void akai_list_tags(struct part_s *pp);
|
||||||
|
extern int akai_rename_tag(struct part_s *pp,char *name,u_int ti,int wipeflag);
|
||||||
|
|
||||||
|
extern void akai_print_cdinfo(struct part_s *pp,int verbose);
|
||||||
|
extern int akai_set_cdinfo(struct part_s *pp,char *cdlabel);
|
||||||
|
|
||||||
|
extern void akai_part_info(struct part_s *pp,int verbose);
|
||||||
|
extern void akai_list_part(struct part_s *pp,int recflag,u_char *filtertagp);
|
||||||
|
extern struct part_s *akai_find_part(struct disk_s *dp,char *name);
|
||||||
|
extern void print_fat(struct part_s *pp);
|
||||||
|
|
||||||
|
extern void akai_disk_info(struct disk_s *dp,int verbose);
|
||||||
|
extern void akai_list_disk(struct disk_s *dp,int recflag,u_char *filtertagp);
|
||||||
|
extern void akai_list_alldisks(int recflag,u_char *filtertagp);
|
||||||
|
|
||||||
|
extern void akai_sort_filetags(u_char *tagp);
|
||||||
|
extern int akai_set_filetag(u_char *tagp,u_int ti);
|
||||||
|
extern int akai_clear_filetag(u_char *tagp,u_int ti);
|
||||||
|
extern int akai_match_filetags(u_char *filtertagp,u_char *testtagp);
|
||||||
|
extern int akai_get_file(struct vol_s *vp,struct file_s *fp,u_int fi);
|
||||||
|
extern int akai_find_file(struct vol_s *vp,struct file_s *fp,char *name);
|
||||||
|
extern int akai_rename_file(struct file_s *fp,char *name,struct vol_s *vp,u_int dstindex,u_char *tagp,u_int osver);
|
||||||
|
#define AKAI_CREATE_FILE_NOINDEX ((u_int)-1) /* no user-supplied index */
|
||||||
|
extern int akai_create_file(struct vol_s *vp,struct file_s *fp,u_int size,u_int index,char *name,u_int osver,u_char *tagp);
|
||||||
|
extern void akai_fvol1000_initfile(struct akai_voldir_entry_s *ep,u_int osver,u_int tag);
|
||||||
|
extern int akai_delete_file(struct file_s *fp);
|
||||||
|
|
||||||
|
extern int akai_rename_ddtake(struct part_s *pp,u_int ti,char *name);
|
||||||
|
extern int akai_delete_ddtake(struct part_s *pp,u_int ti);
|
||||||
|
|
||||||
|
extern void akai_fix_partheadmagic(struct part_s *pp);
|
||||||
|
extern int akai_check_partheadmagic(struct part_s *pp);
|
||||||
|
extern void akai_fix_parttabmagic(struct akai_parttab_s *ptp);
|
||||||
|
extern int akai_check_parttabmagic(struct akai_parttab_s *ptp);
|
||||||
|
|
||||||
|
extern int akai_scan_floppy(struct disk_s *dp);
|
||||||
|
extern int akai_scan_harddisk9(struct disk_s *dp);
|
||||||
|
extern int akai_scan_ddpart(struct disk_s *dp,struct akai_parttab_s *ptp,u_int bstart,u_int pi);
|
||||||
|
extern int akai_scan_disk(struct disk_s *dp,int floppyenable);
|
||||||
|
|
||||||
|
extern int akai_wipe_part(struct part_s *pp,int wipeflag,struct part_s *plistp,u_int pimax,int cdromflag);
|
||||||
|
extern int akai_wipe_harddisk(struct disk_s *dp,u_int bsize,u_int totb,int s3000flag,int cdromflag);
|
||||||
|
extern int akai_wipe_harddisk9(struct disk_s *dp,u_int totb);
|
||||||
|
extern int akai_wipe_floppy(struct disk_s *dp,int lodensflag,int s3000flag,int s900flag);
|
||||||
|
|
||||||
|
extern int change_curdir(char *name,u_int vi,char *lastname,int checklast);
|
||||||
|
extern int change_curdir_home(void);
|
||||||
|
extern void save_curdir(int modflag);
|
||||||
|
extern void restore_curdir(void);
|
||||||
|
extern void curdir_info(int verbose,char *pathbuf);
|
||||||
|
extern void list_curdir(int recflag);
|
||||||
|
extern void list_curfiltertags(void);
|
||||||
|
|
||||||
|
extern int copy_file(struct file_s *srcfp,struct vol_s *dstvp,struct file_s *dstfp,u_int dstindex,char *dstname,int delflag);
|
||||||
|
extern int copy_vol_allfiles(struct vol_s *srcvp,struct part_s *dstpp,char *dstname,int delflag,int verbose);
|
||||||
|
extern int copy_part_allvols(struct part_s *srcpp,struct part_s *dstpp,int delflag,int verbose);
|
||||||
|
|
||||||
|
extern int check_curnosamplervol(void);
|
||||||
|
extern int check_curnosamplerpart(void);
|
||||||
|
extern int check_curnoddpart(void);
|
||||||
|
extern int check_curnopart(void);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* !__AKAIUTIL_H */
|
||||||
+20
@@ -0,0 +1,20 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 9.00
|
||||||
|
# Visual Studio 2005
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "akaiutil", "akaiutil.vcproj", "{3F010352-C096-4963-887A-7C23C83616DF}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Win32 = Debug|Win32
|
||||||
|
Release|Win32 = Release|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{3F010352-C096-4963-887A-7C23C83616DF}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
|
{3F010352-C096-4963-887A-7C23C83616DF}.Debug|Win32.Build.0 = Debug|Win32
|
||||||
|
{3F010352-C096-4963-887A-7C23C83616DF}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
|
{3F010352-C096-4963-887A-7C23C83616DF}.Release|Win32.Build.0 = Release|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
+259
@@ -0,0 +1,259 @@
|
|||||||
|
<?xml version="1.0" encoding="Windows-1252"?>
|
||||||
|
<VisualStudioProject
|
||||||
|
ProjectType="Visual C++"
|
||||||
|
Version="8.00"
|
||||||
|
Name="akaiutil"
|
||||||
|
ProjectGUID="{3F010352-C096-4963-887A-7C23C83616DF}"
|
||||||
|
RootNamespace="akaiutil"
|
||||||
|
Keyword="Win32Proj"
|
||||||
|
>
|
||||||
|
<Platforms>
|
||||||
|
<Platform
|
||||||
|
Name="Win32"
|
||||||
|
/>
|
||||||
|
</Platforms>
|
||||||
|
<ToolFiles>
|
||||||
|
</ToolFiles>
|
||||||
|
<Configurations>
|
||||||
|
<Configuration
|
||||||
|
Name="Debug|Win32"
|
||||||
|
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||||
|
IntermediateDirectory="$(ConfigurationName)"
|
||||||
|
ConfigurationType="1"
|
||||||
|
CharacterSet="1"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXMLDataGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
Optimization="0"
|
||||||
|
PreprocessorDefinitions="WIN32;_VISUALCPP;_DEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;DEBUG"
|
||||||
|
MinimalRebuild="true"
|
||||||
|
BasicRuntimeChecks="3"
|
||||||
|
RuntimeLibrary="3"
|
||||||
|
UsePrecompiledHeader="0"
|
||||||
|
WarningLevel="3"
|
||||||
|
Detect64BitPortabilityProblems="true"
|
||||||
|
DebugInformationFormat="4"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManagedResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLinkerTool"
|
||||||
|
AdditionalDependencies="Winmm.lib"
|
||||||
|
LinkIncremental="2"
|
||||||
|
GenerateDebugInformation="true"
|
||||||
|
SubSystem="1"
|
||||||
|
TargetMachine="1"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCALinkTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManifestTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXDCMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCBscMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCFxCopTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCAppVerifierTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebDeploymentTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"
|
||||||
|
/>
|
||||||
|
</Configuration>
|
||||||
|
<Configuration
|
||||||
|
Name="Release|Win32"
|
||||||
|
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||||
|
IntermediateDirectory="$(ConfigurationName)"
|
||||||
|
ConfigurationType="1"
|
||||||
|
CharacterSet="1"
|
||||||
|
WholeProgramOptimization="1"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXMLDataGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
PreprocessorDefinitions="WIN32;_VISUALCPP;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE"
|
||||||
|
RuntimeLibrary="2"
|
||||||
|
UsePrecompiledHeader="0"
|
||||||
|
WarningLevel="3"
|
||||||
|
Detect64BitPortabilityProblems="true"
|
||||||
|
DebugInformationFormat="3"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManagedResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLinkerTool"
|
||||||
|
AdditionalDependencies="Winmm.lib"
|
||||||
|
LinkIncremental="1"
|
||||||
|
GenerateDebugInformation="true"
|
||||||
|
SubSystem="1"
|
||||||
|
OptimizeReferences="2"
|
||||||
|
EnableCOMDATFolding="2"
|
||||||
|
TargetMachine="1"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCALinkTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManifestTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXDCMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCBscMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCFxCopTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCAppVerifierTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebDeploymentTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"
|
||||||
|
/>
|
||||||
|
</Configuration>
|
||||||
|
</Configurations>
|
||||||
|
<References>
|
||||||
|
</References>
|
||||||
|
<Files>
|
||||||
|
<Filter
|
||||||
|
Name="Quelldateien"
|
||||||
|
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||||
|
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||||
|
>
|
||||||
|
<File
|
||||||
|
RelativePath=".\akaiutil.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\akaiutil_file.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\akaiutil_io.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\akaiutil_main.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\akaiutil_take.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\akaiutil_tar.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\akaiutil_wav.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\commonlib.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
</Filter>
|
||||||
|
<Filter
|
||||||
|
Name="Headerdateien"
|
||||||
|
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||||
|
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||||
|
>
|
||||||
|
<File
|
||||||
|
RelativePath=".\akaiutil.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\akaiutil_file.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\akaiutil_io.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\akaiutil_take.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\akaiutil_tar.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\akaiutil_wav.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\commoninclude.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\fdrawcmd.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
</Filter>
|
||||||
|
<Filter
|
||||||
|
Name="Ressourcendateien"
|
||||||
|
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
|
||||||
|
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
|
||||||
|
>
|
||||||
|
</Filter>
|
||||||
|
</Files>
|
||||||
|
<Globals>
|
||||||
|
</Globals>
|
||||||
|
</VisualStudioProject>
|
||||||
+2940
File diff suppressed because it is too large
Load Diff
+563
@@ -0,0 +1,563 @@
|
|||||||
|
#ifndef __AKAIUTIL_FILE_H
|
||||||
|
#define __AKAIUTIL_FILE_H
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2010,2012,2018,2019,2020 Klaus Michael Indlekofer. All rights reserved.
|
||||||
|
*
|
||||||
|
* m.indlekofer@gmx.de
|
||||||
|
*
|
||||||
|
* This program 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 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include "commoninclude.h"
|
||||||
|
#include "akaiutil.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* AKAI files */
|
||||||
|
|
||||||
|
/* Note: all data types are little endian */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* AKAI file type ranges */
|
||||||
|
#define AKAI_S900_FTYPE_MIN 'A' /* min. file type for S900 */
|
||||||
|
#define AKAI_S900_FTYPE_MAX 'Z' /* max. file type for S900 */
|
||||||
|
#define AKAI_S1000_FTYPE_MIN 'a' /* min. file type for S1000 */
|
||||||
|
#define AKAI_S1000_FTYPE_MAX 'z' /* max. file type for S1000 */
|
||||||
|
#define AKAI_S3000_FTYPE_MIN ('a'+0x80) /* min. file type for S3000 */
|
||||||
|
#define AKAI_S3000_FTYPE_MAX ('z'+0x80) /* max. file type for S3000 */
|
||||||
|
/* Note: exception: AKAI_CDSETUP3000_FTYPE=='T' is within range of file types for S900 */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* AKAI S900 sample header */
|
||||||
|
struct akai_sample900_s{
|
||||||
|
char name[AKAI_NAME_LEN_S900]; /* sample name (in RAM) */
|
||||||
|
u_char dummy1[6]; /* XXX 0x00 */
|
||||||
|
u_char slen[4]; /* number of samples */
|
||||||
|
u_char srate[2]; /* sample rate in Hz */
|
||||||
|
#define SAMPLE900_NPITCH_DEF (60*16) /* default */
|
||||||
|
u_char npitch[2]; /* nominal pitch in 1/16 semitones */
|
||||||
|
u_char loud[2]; /* loudness offset (signed) */
|
||||||
|
#define SAMPLE900_PMODE_ONESHOT 'O'
|
||||||
|
#define SAMPLE900_PMODE_LOOP 'L'
|
||||||
|
#define SAMPLE900_PMODE_ALTLOOP 'A'
|
||||||
|
u_char pmode; /* playback mode */
|
||||||
|
u_char dummy2; /* XXX */
|
||||||
|
u_char end[4]; /* end marker */
|
||||||
|
u_char start[4]; /* start marker */
|
||||||
|
u_char llen[4]; /* loop length */
|
||||||
|
u_char dmadesa[2]; /* address of DMA descriptor list (updated by sampler) */
|
||||||
|
#define SAMPLE900_TYPE_NORM 0x00 /* normal */
|
||||||
|
#define SAMPLE900_TYPE_VELXF 0xff /* velocity crossfade */
|
||||||
|
u_char type; /* sample type */
|
||||||
|
#define SAMPLE900_DIR_NORM 'N'
|
||||||
|
#define SAMPLE900_DIR_REV 'R'
|
||||||
|
u_char dir; /* time direction */
|
||||||
|
u_char dummy3[10]; /* XXX */
|
||||||
|
u_char locat[4]; /* absolute address (updated by sampler) */
|
||||||
|
u_char dummy4[2]; /* XXX */
|
||||||
|
}; /* Note: should be 0x003c Bytes */
|
||||||
|
/* Note: header is followed by sample data (in non-compressed or compressed sample format) */
|
||||||
|
|
||||||
|
/* S900 compressed sample format */
|
||||||
|
#define SAMPLE900COMPR_GROUP_SAMPNUM 10 /* number of samples per group */
|
||||||
|
#define SAMPLE900COMPR_UPBITNUM_NEGCODE_OFF 16 /* offset between bit number for upabsval and -code */
|
||||||
|
#define SAMPLE900COMPR_UPBITNUM_MAX 12 /* max. bit number to be used for upabsval */
|
||||||
|
#define SAMPLE900COMPR_INTERVALSIZ (1<<SAMPLE900COMPR_UPBITNUM_MAX) /* interval size for max. bit number */
|
||||||
|
#define SAMPLE900COMPR_BITMASK (SAMPLE900COMPR_INTERVALSIZ-1) /* bit mask for interval */
|
||||||
|
#define SAMPLE900COMPR_INTERVALSIZ2 (SAMPLE900COMPR_INTERVALSIZ>>1) /* half interval size */
|
||||||
|
|
||||||
|
#define AKAI_SAMPLE900_FTYPE 'S' /* file type */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* AKAI S900 program header */
|
||||||
|
struct akai_program900_s{
|
||||||
|
char name[AKAI_NAME_LEN_S900]; /* program name (in RAM) */
|
||||||
|
u_char dummy1[6]; /* XXX 0x00 */
|
||||||
|
u_char dummy2[2]; /* XXX */
|
||||||
|
#define PROGRAM900_KGA_NONE 0x0000 /* value for none */
|
||||||
|
u_char kg1a[2]; /* address of keygroup 1 (updated by sampler) */
|
||||||
|
u_char dummy3; /* XXX */
|
||||||
|
u_char kgxf; /* keygroup (positional) crossfade enable */
|
||||||
|
u_char dummy4; /* XXX */
|
||||||
|
u_char kgnum; /* number of keygroups */
|
||||||
|
u_char dummy5[14]; /* XXX */
|
||||||
|
}; /* Note: should be 0x0026 Bytes */
|
||||||
|
/* Note: header is followed by keygroups */
|
||||||
|
|
||||||
|
/* AKAI S900 program: keygroup */
|
||||||
|
struct akai_program900kg_s{
|
||||||
|
u_char keyhi; /* high MIDI key */
|
||||||
|
u_char keylo; /* low MIDI key */
|
||||||
|
#define PROGRAM900KG_VELSWTH_NOSOFT 0 /* value for no soft sample */
|
||||||
|
#define PROGRAM900KG_VELSWTH_NOLOUD 128 /* value for no loud sample */
|
||||||
|
u_char velswth; /* velocity switch threshold */
|
||||||
|
u_char dummy1[15]; /* XXX */
|
||||||
|
#define PROGRAM900KG_FLAGS_PCONST 0x01 /* constant pitch enable */
|
||||||
|
#define PROGRAM900KG_FLAGS_VELXF 0x02 /* velocity crossfade enable */
|
||||||
|
#define PROGRAM900KG_FLAGS_ONESHOT 0x08 /* one-shot trigger mode enable */
|
||||||
|
u_char flags; /* flags */
|
||||||
|
#define PROGRAM900KG_OUTCH1_LEFT 0x08 /* code for LEFT */
|
||||||
|
#define PROGRAM900KG_OUTCH1_RIGHT 0x09 /* code for RIGHT */
|
||||||
|
#define PROGRAM900KG_OUTCH1_ANY 0xff /* code for ANY */
|
||||||
|
u_char outch1; /* audio output channel: channel number-1 or code */
|
||||||
|
u_char midichoff; /* MIDI channel offset */
|
||||||
|
u_char dummy2[3]; /* XXX */
|
||||||
|
u_char sname1[AKAI_NAME_LEN_S900]; /* sample name (in RAM) for sample 1 ("soft") */
|
||||||
|
u_char dummy3[4]; /* XXX */
|
||||||
|
u_char velxfv50; /* if velocity crossfade: velocity value for 50% */
|
||||||
|
u_char dummy4; /* XXX */
|
||||||
|
#define PROGRAM900KG_SHDRA_NONE 0x0000 /* value for none */
|
||||||
|
u_char shdra1[2]; /* address of sample header for sample 1 (updated by sampler) */
|
||||||
|
u_char tune1[2]; /* tuning offset (transpose) in 1/16 semitones (signed) for sample 1 */
|
||||||
|
u_char filter1; /* filter for sample 1 */
|
||||||
|
u_char loud1; /* loudness offset (signed) for sample 1 */
|
||||||
|
u_char sname2[AKAI_NAME_LEN_S900]; /* sample name (in RAM) for sample 2 ("loud") */
|
||||||
|
u_char dummy5[6]; /* XXX */
|
||||||
|
u_char shdra2[2]; /* address of sample header for sample 2 (updated by sampler) */
|
||||||
|
u_char tune2[2]; /* tuning offset in 1/16 semitones (signed) for sample 2 */
|
||||||
|
u_char filter2; /* filter for sample 2 */
|
||||||
|
u_char loud2; /* loudness offset (signed) for sample 2 */
|
||||||
|
u_char kgnexta[2]; /* address of next keygroup (updated by sampler) */
|
||||||
|
}; /* Note: should be 0x0046 Bytes */
|
||||||
|
|
||||||
|
#define AKAI_PROGRAM900_FTYPE 'P' /* file type */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* AKAI S900/S950 drum settings descriptor */
|
||||||
|
struct akai_drum900des_s{
|
||||||
|
u_char inpnr1; /* input number-1 */
|
||||||
|
u_char midich1; /* MIDI channel-1 */
|
||||||
|
u_char midinote; /* MIDI note */
|
||||||
|
u_char gain; /* gain */
|
||||||
|
u_char ask90_trig; /* if ASK90: trigger threshold */
|
||||||
|
/* if ME35T: (ignored) */
|
||||||
|
u_char dummy1[3]; /* XXX */
|
||||||
|
#define DRUM900DES_ITYPE_ASK90 0x00 /* interface type: ASK90 */
|
||||||
|
#define DRUM900DES_ITYPE_ME35T 0xff /* interface type: ME35T */
|
||||||
|
u_char itype; /* interface type */
|
||||||
|
u_char me35t_trig; /* if ASK90: (ignored) */
|
||||||
|
/* if ME35T: trigger threshold */
|
||||||
|
u_char me35t_vcurv1; /* if ASK90: (ignored) */
|
||||||
|
/* if ME35T: "V-curve"-1 */
|
||||||
|
u_char dummy2; /* XXX */
|
||||||
|
u_char captt4[2]; /* 4* capture time in msec */
|
||||||
|
u_char ontime4[2]; /* 4* on-time in msec */
|
||||||
|
u_char recovt4[2]; /* 4* recovery time in msec */
|
||||||
|
u_char dummy3[8];
|
||||||
|
u_char ask90_resba[2]; /* if ASK90: ASK90 base address for CH RESET */
|
||||||
|
/* if ME35T: (ignored) */
|
||||||
|
u_char ask90_adcla[2]; /* if ASK90: ASK90 address for ADC latch */
|
||||||
|
/* if ME35T: (ignored) */
|
||||||
|
}; /* Note: should be 0x001e Bytes */
|
||||||
|
|
||||||
|
/* AKAI S900/S950 drum settings file */
|
||||||
|
struct akai_drum900_s{
|
||||||
|
u_char ask90enab; /* if ASK90: ASK90 enable */
|
||||||
|
/* if ME35T: (ignored) */
|
||||||
|
u_char ask90sens; /* if ASK90: ASK90 sensitivity */
|
||||||
|
/* if ME35T: (ignored) */
|
||||||
|
u_char dummy1[20]; /* XXX 0x00 ... 0x00 */
|
||||||
|
#define DRUM900_INPUTNUM 8 /* number of drum trigger inputs */
|
||||||
|
struct akai_drum900des_s ddes[DRUM900_INPUTNUM]; /* drum setting descriptors */
|
||||||
|
}; /* Note: should be 0x0106 Bytes */
|
||||||
|
|
||||||
|
#define AKAI_DRUM900_FTYPE 'D' /* file type */
|
||||||
|
#define AKAI_DRUM900_FNAME "DRUM SET " /* default file name */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* AKAI S900 overall settings file */
|
||||||
|
struct akai_ovs900_s{
|
||||||
|
char progname[AKAI_NAME_LEN_S900]; /* selected program name */
|
||||||
|
u_char dummy1[6]; /* XXX 0x20 ... 0x20 */
|
||||||
|
u_char dummy2[4]; /* XXX */
|
||||||
|
u_char testmidich[2]; /* test MIDI channel */
|
||||||
|
u_char testmidikey[2]; /* test MIDI key */
|
||||||
|
u_char testmidivel[2]; /* test MIDI velocity */
|
||||||
|
u_char dummy3; /* XXX */
|
||||||
|
#define OVS900_BMIDICH1MASK 0x7f /* bit mask for basic MIDI channel-1 */
|
||||||
|
#define OVS900_OMNIMASK 0x80 /* bit mask for OMNI flag */
|
||||||
|
u_char bmidich1omni; /* basic MIDI channel-1 | OMNI flag */
|
||||||
|
u_char loudness; /* loudness enable */
|
||||||
|
#define OVS900_CTRLPORT_MIDI 0x01 /* control port: MIDI */
|
||||||
|
#define OVS900_CTRLPORT_RS232 0x02 /* control port: RS232 */
|
||||||
|
u_char ctrlport; /* control port */
|
||||||
|
u_char progchange; /* program change enable */
|
||||||
|
u_char dummy4[4]; /* XXX */
|
||||||
|
u_char pwheelrange; /* pitch wheel range */
|
||||||
|
u_char rs232brate10[2]; /* RS232 baudrate/10 */
|
||||||
|
u_char dummy5[2]; /* XXX */
|
||||||
|
}; /* Note: should be 0x0028 Bytes */
|
||||||
|
|
||||||
|
#define AKAI_OVS900_FTYPE 'O' /* file type */
|
||||||
|
#define AKAI_OVS900_FNAME "OVERALL SE" /* default file name */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* AKAI S900 fixup file */
|
||||||
|
#define AKAI_FIXUP900_FTYPE 'F' /* file type */
|
||||||
|
|
||||||
|
/* AKAI S900 memory image file */
|
||||||
|
#define AKAI_MEMIMG900_FTYPE 'M' /* file type */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* AKAI S1000 empty file name */
|
||||||
|
#define AKAI_EMPTY1000_FNAME "VVVVVVVVVVVV" /* S1000 empty file name */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* AKAI S1000 generic header */
|
||||||
|
struct akai_genfilehdr_s{
|
||||||
|
u_char blockid; /* block ID */
|
||||||
|
u_char dummy1[2]; /* XXX */
|
||||||
|
u_char name[AKAI_NAME_LEN]; /* file name (in RAM) */
|
||||||
|
}; /* Note: should be 0x000f Bytes */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* AKAI S1000 sample loop parameters */
|
||||||
|
struct akai_sample1000loop_s{
|
||||||
|
u_char at[4]; /* loop at marker */
|
||||||
|
u_char flen[2]; /* loop fine length in 1/65536 sample */
|
||||||
|
u_char len[4]; /* loop length in samples */
|
||||||
|
#define SAMPLE1000LOOP_TIME_NOLOOP 0 /* value for NOLOOP */
|
||||||
|
#define SAMPLE1000LOOP_TIME_HOLD 9999 /* value for HOLD */
|
||||||
|
u_char time[2]; /* loop time in msec */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* AKAI S1000 sample header */
|
||||||
|
struct akai_sample1000_s{
|
||||||
|
#define SAMPLE1000_BLOCKID 0x03
|
||||||
|
u_char blockid; /* block ID */
|
||||||
|
#define SAMPLE1000_BANDW_10KHZ 0x00
|
||||||
|
#define SAMPLE1000_BANDW_20KHZ 0x01
|
||||||
|
u_char bandw; /* bandwidth select */
|
||||||
|
u_char rkey; /* MIDI root key (typ. 0x3c) */
|
||||||
|
u_char name[AKAI_NAME_LEN]; /* sample name (in RAM) */
|
||||||
|
u_char dummy1; /* XXX 0x80 */
|
||||||
|
u_char lnum; /* number of loops */
|
||||||
|
u_char lfirst; /* first active loop-1 */
|
||||||
|
u_char dummy2; /* XXX 0x00 */
|
||||||
|
#define SAMPLE1000_PMODE_LOOP 0x00
|
||||||
|
#define SAMPLE1000_PMODE_LOOPNOTREL 0x01
|
||||||
|
#define SAMPLE1000_PMODE_NOLOOP 0x02
|
||||||
|
#define SAMPLE1000_PMODE_TOEND 0x03
|
||||||
|
u_char pmode; /* playback mode */
|
||||||
|
u_char ctune; /* cents tune (signed) */
|
||||||
|
u_char stune; /* semitone tune (signed) */
|
||||||
|
u_char locat[4]; /* absolute address (updated by sampler) */
|
||||||
|
u_char slen[4]; /* number of samples */
|
||||||
|
u_char start[4]; /* start marker */
|
||||||
|
u_char end[4]; /* end marker */
|
||||||
|
#define AKAI_SAMPLE1000_LOOPNUM 8
|
||||||
|
struct akai_sample1000loop_s loop[AKAI_SAMPLE1000_LOOPNUM];
|
||||||
|
u_char dummy3[2]; /* XXX 0x00 0x00 */
|
||||||
|
#define AKAI_SAMPLE1000_STPAIRA_NONE 0xffff /* value for none */
|
||||||
|
u_char stpaira[2]; /* address of sample header of partner in stereo pair (updated by sampler) */
|
||||||
|
u_char srate[2]; /* sample rate in Hz */
|
||||||
|
u_char hltoff; /* HOLD loop tune offset */
|
||||||
|
u_char dummy4[9]; /* XXX 0x00 ... 0x00 */
|
||||||
|
}; /* Note: should be 0x0096 Bytes */
|
||||||
|
/* Note: header is followed by sample data */
|
||||||
|
|
||||||
|
#define AKAI_SAMPLE1000_FTYPE 's' /* file type */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* AKAI S3000 sample header */
|
||||||
|
struct akai_sample3000_s{
|
||||||
|
#define SAMPLE3000_BLOCKID SAMPLE1000_BLOCKID
|
||||||
|
struct akai_sample1000_s s1000;
|
||||||
|
u_char dummy1[42]; /* XXX 0x00 ... 0x00 */
|
||||||
|
}; /* Note: should be 0x00c0 Bytes */
|
||||||
|
/* Note: header is followed by sample data */
|
||||||
|
|
||||||
|
/* address multiplicand */
|
||||||
|
#define SAMPLE3000_STPAIRA_MULT 0x10
|
||||||
|
|
||||||
|
#define AKAI_SAMPLE3000_FTYPE ('s'+0x80) /* file type */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* AKAI CD3000 CD-ROM sample parameters file */
|
||||||
|
/* Note: contains S3000 sample header */
|
||||||
|
#define AKAI_CDSAMPLE3000_FTYPE ('h'+0x80) /* file type */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* AKAI S1000 program header */
|
||||||
|
struct akai_program1000_s{
|
||||||
|
#define PROGRAM1000_BLOCKID 0x01
|
||||||
|
u_char blockid; /* block ID */
|
||||||
|
#define PROGRAM1000_KGA_NONE 0x0000 /* value for none */
|
||||||
|
u_char kg1a[2]; /* address of keygroup 1 (updated by sampler) */
|
||||||
|
u_char name[AKAI_NAME_LEN]; /* program name (in RAM) */
|
||||||
|
u_char dummy1; /* XXX */
|
||||||
|
#define PROGRAM1000_MIDICH1_OMNI 0xff /* code for OMNI */
|
||||||
|
u_char midich1; /* MIDI channel number-1 or code */
|
||||||
|
u_char dummy2[2]; /* XXX */
|
||||||
|
u_char keylo; /* low MIDI key */
|
||||||
|
u_char keyhi; /* high MIDI key */
|
||||||
|
u_char oct; /* octave offset (signed) */
|
||||||
|
#define PROGRAM1000_AUXCH1_OFF 0xff /* code for OFF */
|
||||||
|
u_char auxch1; /* aux output channel number-1 or code */
|
||||||
|
u_char dummy3[18]; /* XXX */
|
||||||
|
u_char kgxf; /* keygroup crossfade enable */
|
||||||
|
u_char kgnum; /* number of keygroups */
|
||||||
|
u_char dummy4[107]; /* XXX */
|
||||||
|
}; /* Note: should be 0x0096 Bytes */
|
||||||
|
/* Note: header is followed by keygroups */
|
||||||
|
|
||||||
|
/* AKAI S1000 program keygroup: velocity zone */
|
||||||
|
struct akai_program1000kgvelzone_s{
|
||||||
|
u_char sname[AKAI_NAME_LEN]; /* sample name (in RAM) */
|
||||||
|
u_char vello; /* low MIDI velocity */
|
||||||
|
u_char velhi; /* high MIDI velocity */
|
||||||
|
u_char ctune; /* cents tune offset (signed) */
|
||||||
|
u_char stune; /* semitone tune offset (signed) */
|
||||||
|
u_char loud; /* loudness offset (signed) */
|
||||||
|
u_char filter; /* filter offset (signed) */
|
||||||
|
u_char pan; /* pan offset (signed) */
|
||||||
|
#define PROGRAM1000_PMODE_SAMPLE 0x00
|
||||||
|
#define PROGRAM1000_PMODE_LOOP 0x01
|
||||||
|
#define PROGRAM1000_PMODE_LOOPNOTREL 0x02
|
||||||
|
#define PROGRAM1000_PMODE_NOLOOP 0x03
|
||||||
|
#define PROGRAM1000_PMODE_TOEND 0x04
|
||||||
|
u_char pmode; /* playback mode */
|
||||||
|
u_char dummy1[2]; /* XXX */
|
||||||
|
#define PROGRAM1000KG_SHDRA_NONE 0xffff /* value for none */
|
||||||
|
u_char shdra[2]; /* address of sample header (updated by sampler) */
|
||||||
|
}; /* Note: should be 0x0018 Bytes */
|
||||||
|
|
||||||
|
/* AKAI S1000 program: keygroup */
|
||||||
|
struct akai_program1000kg_s{
|
||||||
|
#define PROGRAM1000KG_BLOCKID 0x02
|
||||||
|
u_char blockid; /* block ID */
|
||||||
|
u_char kgnexta[2]; /* address of next keygroup (updated by sampler) */
|
||||||
|
u_char keylo; /* low MIDI key */
|
||||||
|
u_char keyhi; /* high MIDI key */
|
||||||
|
u_char ctune; /* cents tune offset (signed) */
|
||||||
|
u_char stune; /* semitone tune offset (signed) */
|
||||||
|
u_char filter; /* filter */
|
||||||
|
u_char dummy1[22]; /* XXX */
|
||||||
|
u_char velxf; /* velocity crossfade enable */
|
||||||
|
u_char dummy2[3]; /* XXX */
|
||||||
|
#define PROGRAM1000KG_VELZONENUM 4 /* number of velocity zones per keygroup */
|
||||||
|
struct akai_program1000kgvelzone_s velzone[PROGRAM1000KG_VELZONENUM]; /* velocity zones */
|
||||||
|
u_char dummy3[2]; /* XXX */
|
||||||
|
u_char pconst[PROGRAM1000KG_VELZONENUM]; /* constant pitch enable for velocity zones */
|
||||||
|
u_char auxchoff[PROGRAM1000KG_VELZONENUM]; /* aux output channel offsets for velocity zones */
|
||||||
|
u_char dummy4[10]; /* XXX */
|
||||||
|
}; /* Note: should be 0x0096 Bytes */
|
||||||
|
|
||||||
|
#define AKAI_PROGRAM1000_FTYPE 'p' /* file type */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* AKAI S3000 program header */
|
||||||
|
struct akai_program3000_s{
|
||||||
|
#define PROGRAM3000_BLOCKID PROGRAM1000_BLOCKID
|
||||||
|
struct akai_program1000_s s1000;
|
||||||
|
u_char dummy1[42]; /* XXX */
|
||||||
|
}; /* Note: should be 0x00c0 Bytes */
|
||||||
|
/* Note: header is followed by keygroups */
|
||||||
|
|
||||||
|
/* AKAI S3000 program: keygroup */
|
||||||
|
struct akai_program3000kg_s{
|
||||||
|
#define PROGRAM3000KG_BLOCKID PROGRAM1000KG_BLOCKID
|
||||||
|
struct akai_program1000kg_s s1000;
|
||||||
|
u_char dummy1[42]; /* XXX */
|
||||||
|
}; /* Note: should be 0x00c0 Bytes */
|
||||||
|
|
||||||
|
/* address multiplicands */
|
||||||
|
#define PROGRAM3000_KGA_MULT 0x10
|
||||||
|
#define PROGRAM3000_SHDRA_MULT 0x10
|
||||||
|
|
||||||
|
#define AKAI_PROGRAM3000_FTYPE ('p'+0x80) /* file type */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* AKAI S1000 or S3000 drum settings descriptor */
|
||||||
|
struct akai_drum1000des_s{
|
||||||
|
u_char midich1; /* MIDI channel-1 */
|
||||||
|
u_char midinote; /* MIDI note */
|
||||||
|
u_char sens; /* sensitivity level */
|
||||||
|
u_char trig; /* trigger level */
|
||||||
|
u_char vcurv1; /* "V-curve"-1 */
|
||||||
|
u_char captt; /* capture time in msec */
|
||||||
|
u_char recovt; /* recovery time in msec */
|
||||||
|
u_char ontime; /* on-time in msec */
|
||||||
|
u_char dummy1; /* XXX */
|
||||||
|
}; /* Note: should be 0x0009 Bytes */
|
||||||
|
|
||||||
|
/* AKAI S1000 or S3000 drum settings file */
|
||||||
|
struct akai_drum1000_s{
|
||||||
|
#define DRUM1000_BLOCKID 0x01
|
||||||
|
u_char blockid; /* block ID */
|
||||||
|
u_char dummy1[2]; /* XXX */
|
||||||
|
u_char name[AKAI_NAME_LEN]; /* drum settings name (in RAM) */
|
||||||
|
#define DRUM1000_UNITNUM 2 /* number of units */
|
||||||
|
#define DRUM1000_INPUTNUM 8 /* number of drum trigger inputs per unit */
|
||||||
|
struct akai_drum1000des_s ddes1[DRUM1000_INPUTNUM]; /* drum setting descriptors for unit 1 */
|
||||||
|
u_char dummy2[3]; /* XXX */
|
||||||
|
struct akai_drum1000des_s ddes2[DRUM1000_INPUTNUM]; /* drum setting descriptors for unit 2 */
|
||||||
|
}; /* Note: should be 0x00a2 Bytes */
|
||||||
|
|
||||||
|
#define AKAI_DRUM1000_FTYPE 'd' /* file type */
|
||||||
|
#define AKAI_DRUM1000_FNAME "DRUM INPUTS " /* default file name */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* AKAI S1100 or S3000 or S3000XL effects file */
|
||||||
|
/* Note: effects files of different system types are incompatible */
|
||||||
|
#define AKAI_FXFILE_FTYPE 'x' /* file type */
|
||||||
|
#define AKAI_FXFILE_FNAME "EFFECTS FILE" /* default file name */
|
||||||
|
#define AKAI_FXFILE_FSIZE 0x1c90 /* default file size */
|
||||||
|
#define FXFILE1100_BLOCKID 0x00
|
||||||
|
#define FXFILE3000_BLOCKID 0x00
|
||||||
|
#define FXFILE3000XL_BLOCKID 0x02
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* AKAI S1100 or S3000 cue/take-list header */
|
||||||
|
struct akai_cuelist_s{
|
||||||
|
#define CUELIST_BLOCKID 0x00
|
||||||
|
u_char blockid; /* block ID */
|
||||||
|
u_char dummy1[2]; /* XXX */
|
||||||
|
u_char name[AKAI_NAME_LEN]; /* cue/take-list name (in RAM) */
|
||||||
|
u_char dummy2[7]; /* XXX */
|
||||||
|
u_char cuenum; /* number of cues */
|
||||||
|
u_char dummy3[105]; /* XXX */
|
||||||
|
}; /* Note: should be 0x0080 Bytes */
|
||||||
|
/* Note: header is followed by cues */
|
||||||
|
|
||||||
|
/* AKAI S1100 or S3000 cue */
|
||||||
|
/* Note: depending on file/cue type, some struct elements are ignored */
|
||||||
|
struct akai_cue_s{
|
||||||
|
u_char name[AKAI_NAME_LEN]; /* program or take name */
|
||||||
|
u_char time[5]; /* time (BCD format) */
|
||||||
|
#define AKAI_CUETYPE_MOFF 0x00 /* program: MIDI note off */
|
||||||
|
#define AKAI_CUETYPE_MON 0x01 /* program: MIDI note on */
|
||||||
|
#define AKAI_CUETYPE_TOFF 0x02 /* DD take: off */
|
||||||
|
#define AKAI_CUETYPE_TON 0x03 /* DD take: on */
|
||||||
|
u_char type; /* cue type */
|
||||||
|
u_char midinote; /* MIDI note */
|
||||||
|
u_char midivel; /* MIDI velocity */
|
||||||
|
u_char pan; /* panning (signed) */
|
||||||
|
u_char stlvl; /* stereo output level */
|
||||||
|
u_char midich1; /* MIDI channel-1 */
|
||||||
|
u_char repeat1; /* repeat count-1 */
|
||||||
|
u_char fadein[2]; /* fade in time in ms */
|
||||||
|
u_char fadeout[2]; /* fade out time in ms */
|
||||||
|
u_char dummy1[4]; /* XXX */
|
||||||
|
}; /* Note: should be 0x0020 Bytes */
|
||||||
|
|
||||||
|
#define AKAI_QLFILE_FTYPE 'q' /* cue-list file type */
|
||||||
|
#define AKAI_QLFILE_FNAME "QL1 " /* default cue-list file name */
|
||||||
|
|
||||||
|
#define AKAI_TLFILE_FTYPE 't' /* take-list file type */
|
||||||
|
#define AKAI_TLFILE_FNAME "TL1 " /* default take-list file name */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* AKAI S3000 multi file */
|
||||||
|
#define AKAI_MULTI3000_FTYPE ('m'+0x80) /* file type */
|
||||||
|
#define AKAI_MULTI3000_FNAME "MULTI FILE " /* default file name */
|
||||||
|
#define MULTI3000_BLOCKID 0x00
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* AKAI S1000 operating system file */
|
||||||
|
#define AKAI_SYS1000_FTYPE 'c' /* file type */
|
||||||
|
|
||||||
|
/* AKAI S3000 operating system file */
|
||||||
|
#define AKAI_SYS3000_FTYPE ('c'+0x80) /* file type */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* AKAI CD3000 CD-ROM setup header */
|
||||||
|
/* Note: generic file header does not apply for this file type! */
|
||||||
|
struct akai_cdsetup3000_s{
|
||||||
|
u_char name[AKAI_NAME_LEN]; /* CD-ROM setup name (in RAM) */
|
||||||
|
u_char dummy1[3]; /* XXX */
|
||||||
|
u_char cdlabel[AKAI_NAME_LEN]; /* CD-ROM label */
|
||||||
|
}; /* Note: should be 0x006b Bytes */
|
||||||
|
/* followed by marked file entries */
|
||||||
|
|
||||||
|
/* marked file entry */
|
||||||
|
struct akai_cdsetup3000_entry_s{
|
||||||
|
u_char parti; /* partition index */
|
||||||
|
u_char voli; /* volume index */
|
||||||
|
u_char filei[2]; /* file index */
|
||||||
|
}; /* Note: should be 4 Bytes */
|
||||||
|
/* Note: unused entry is 0xff 0xff 0xff 0xff */
|
||||||
|
|
||||||
|
#define AKAI_CDSETUP3000_FTYPE 'T' /* file type */
|
||||||
|
/* Note: AKAI_CDSETUP3000_FTYPE is within range of file types for S900 */
|
||||||
|
#define AKAI_CDSETUP3000_FNAME "NEW CD SETUP" /* default file name */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Declarations */
|
||||||
|
|
||||||
|
extern int akai_file_info(struct file_s *fp,int verbose);
|
||||||
|
extern void akai_sample_info(struct file_s *fp,u_char *hdrp);
|
||||||
|
extern int akai_program_info(struct file_s *fp);
|
||||||
|
extern int akai_cuelist_info(struct file_s *fp);
|
||||||
|
extern int akai_takelist_info(struct file_s *fp);
|
||||||
|
extern int akai_drum1000_info(struct file_s *fp);
|
||||||
|
extern int akai_drum900_info(struct file_s *fp);
|
||||||
|
extern int akai_ovs900_info(struct file_s *fp);
|
||||||
|
extern int akai_cdsetup3000_info(struct file_s *fp);
|
||||||
|
|
||||||
|
extern int akai_fixramname(struct file_s *fp);
|
||||||
|
|
||||||
|
extern int akai_s900comprfile_updateuncompr(struct file_s *fp);
|
||||||
|
|
||||||
|
extern u_int akai_sample900_getsamplesize(struct file_s *fp);
|
||||||
|
|
||||||
|
extern void akai_sample900noncompr_sample2wav(u_char *sbuf,u_char *wavbuf,u_int samplecountpart);
|
||||||
|
extern void akai_sample900noncompr_wav2sample(u_char *sbuf,u_char *wavbuf,u_int samplecountpart);
|
||||||
|
|
||||||
|
extern u_int akai_sample900compr_getbits(u_char *buf,u_int bitpos,u_int bitnum);
|
||||||
|
extern u_int akai_sample900compr_sample2wav(u_char *sbuf,u_char *wavbuf,u_int sbufsiz,u_int wavbufsiz);
|
||||||
|
extern void akai_sample900compr_setbits(u_char *buf,u_int bitpos,u_int bitnum,u_int val);
|
||||||
|
extern int akai_sample900compr_wav2sample(u_char *sbuf,u_char *wavbuf,u_int samplecountpart);
|
||||||
|
|
||||||
|
extern int akai_sample900_noncompr2compr(struct file_s *fp,struct vol_s *volp);
|
||||||
|
extern int akai_sample900_compr2noncompr(struct file_s *fp,struct vol_s *volp);
|
||||||
|
|
||||||
|
#define SAMPLE2WAV_CHECK 1
|
||||||
|
#define SAMPLE2WAV_EXPORT 2
|
||||||
|
#define SAMPLE2WAV_CREATE 4
|
||||||
|
#define SAMPLE2WAV_ALL 0xff
|
||||||
|
extern int akai_sample2wav(struct file_s *fp,int wavfd,u_int *sizep,char **wavnamep,int what);
|
||||||
|
|
||||||
|
#define WAV2SAMPLE_OPEN 1
|
||||||
|
#define WAV2SAMPLE_OVERWRITE 2
|
||||||
|
extern int akai_wav2sample(int wavfd,char *wavname,struct vol_s *volp,u_int findex,
|
||||||
|
u_int type,int s9cflag,u_int osver,u_char *tagp,
|
||||||
|
u_int *bcountp,int what);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* !__AKAIUTIL_FILE_H */
|
||||||
+865
@@ -0,0 +1,865 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2008,2019,2020,2021 Klaus Michael Indlekofer. All rights reserved.
|
||||||
|
*
|
||||||
|
* m.indlekofer@gmx.de
|
||||||
|
*
|
||||||
|
* This program 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 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include "commoninclude.h"
|
||||||
|
#include "akaiutil_io.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef _VISUALCPP
|
||||||
|
/* for low-level floppy I/O, using fdrawcmd.sys */
|
||||||
|
#include "fdrawcmd.h" /* from http://simonowen.com/fdrawcmd/fdrawcmd.h */
|
||||||
|
|
||||||
|
HANDLE fldr_h[FLDRNUM]; /* handle for floppy drive */
|
||||||
|
u_int fldr_type[FLDRNUM]; /* floppy drive type */
|
||||||
|
PBYTE fldr_secbuf; /* DMA buffer for sector */
|
||||||
|
|
||||||
|
int
|
||||||
|
fldr_init(void)
|
||||||
|
{
|
||||||
|
u_int i;
|
||||||
|
|
||||||
|
for (i=0;i<FLDRNUM;i++){
|
||||||
|
fldr_h[i]=INVALID_HANDLE_VALUE;
|
||||||
|
fldr_type[i]=FLDR_TYPE_FLL; /* XXX */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* allocate DMA buffer for sector */
|
||||||
|
fldr_secbuf=(PBYTE)VirtualAlloc(NULL,AKAI_FL_SECSIZE,MEM_COMMIT,PAGE_READWRITE);
|
||||||
|
if (fldr_secbuf==NULL){
|
||||||
|
PRINTF_ERR("fldr_init: cannot allocate DMA buffer\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
fldr_end(void)
|
||||||
|
{
|
||||||
|
u_int i;
|
||||||
|
|
||||||
|
for (i=0;i<FLDRNUM;i++){
|
||||||
|
if (fldr_h[i]!=INVALID_HANDLE_VALUE){
|
||||||
|
CloseHandle(fldr_h[i]);
|
||||||
|
fldr_h[i]=INVALID_HANDLE_VALUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (fldr_secbuf!=NULL){
|
||||||
|
VirtualFree(fldr_secbuf,0,MEM_RELEASE);
|
||||||
|
fldr_secbuf=NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
fldr_open(int fldrn,u_int fldrtype)
|
||||||
|
{
|
||||||
|
static char devname[32]; /* XXX */
|
||||||
|
HANDLE h;
|
||||||
|
DWORD version;
|
||||||
|
BYTE datarate;
|
||||||
|
DWORD ret;
|
||||||
|
|
||||||
|
if ((fldrn<0)||(fldrn>=FLDRNUM)){
|
||||||
|
PRINTF_ERR("fldr_open: invalid floppy drive number\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (fldr_h[fldrn]!=INVALID_HANDLE_VALUE){
|
||||||
|
PRINTF_ERR("fldr_open: floppy drive already opened\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check driver */
|
||||||
|
version=0; /* invalid */
|
||||||
|
/* Note: must use GENERIC_READ|GENERIC_WRITE for DeviceIoControl() */
|
||||||
|
h=CreateFileA("\\\\.\\fdrawcmd",GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL);
|
||||||
|
if (h!=INVALID_HANDLE_VALUE){
|
||||||
|
if (!DeviceIoControl(h,IOCTL_FDRAWCMD_GET_VERSION,NULL,0,&version,sizeof(version),&ret,NULL)){
|
||||||
|
version=0; /* invalid */
|
||||||
|
}
|
||||||
|
CloseHandle(h);
|
||||||
|
}
|
||||||
|
if (version==0){
|
||||||
|
PRINTF_ERR("fldr_open: fdrawcmd.sys is not installed, see: http://simonowen.com/fdrawcmd/\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (HIWORD(version)!=HIWORD(FDRAWCMD_VERSION)){
|
||||||
|
PRINTF_ERR("fldr_open: the installed fdrawcmd.sys is not compatible with this program\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* open and init device */
|
||||||
|
sprintf(devname,"\\\\.\\fdraw%u",(u_int)fldrn);
|
||||||
|
/* Note: must use GENERIC_READ|GENERIC_WRITE for DeviceIoControl() */
|
||||||
|
h=CreateFileA(devname,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL);
|
||||||
|
if (h==INVALID_HANDLE_VALUE){
|
||||||
|
PRINTF_ERR("fldr_open: cannot open floppy drive\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (fldrtype==FLDR_TYPE_FLH){
|
||||||
|
datarate=AKAI_FLH_DISK_DATARATE;
|
||||||
|
}else{
|
||||||
|
datarate=AKAI_FLL_DISK_DATARATE;
|
||||||
|
}
|
||||||
|
if (!DeviceIoControl(h,IOCTL_FD_SET_DATA_RATE,&datarate,sizeof(datarate),NULL,0,&ret,NULL)){
|
||||||
|
PRINTF_ERR("fldr_open: cannot set floppy data rate\n");
|
||||||
|
CloseHandle(h);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (!DeviceIoControl(h,IOCTL_FD_RESET,NULL,0,NULL,0,&ret,NULL)){
|
||||||
|
PRINTF_ERR("fldr_open: cannot reset floppy controller\n");
|
||||||
|
CloseHandle(h);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* save handle and type */
|
||||||
|
fldr_h[fldrn]=h;
|
||||||
|
fldr_type[fldrn]=fldrtype;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
fldr_checkfloppyinserted(int fldrn)
|
||||||
|
{
|
||||||
|
DWORD ret;
|
||||||
|
|
||||||
|
if ((fldrn<0)||(fldrn>=FLDRNUM)||(fldr_h[fldrn]==INVALID_HANDLE_VALUE)){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check if no floppy inserted */
|
||||||
|
if (!DeviceIoControl(fldr_h[fldrn],IOCTL_FD_CHECK_DISK,NULL,0,NULL,0,&ret,NULL)){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0; /* floppy is inserted */
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
fldr_io_direct(int fldrn,u_int blk,u_char *buf,int mode)
|
||||||
|
{
|
||||||
|
BYTE cyl;
|
||||||
|
BYTE head;
|
||||||
|
BYTE sec;
|
||||||
|
DWORD ret;
|
||||||
|
FD_READ_WRITE_PARAMS rwp;
|
||||||
|
u_int retry;
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
if ((fldrn<0)||(fldrn>=FLDRNUM)||(fldr_h[fldrn]==INVALID_HANDLE_VALUE)||(buf==NULL)){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if ((mode!=IO_BLKS_READ)&&(mode!=IO_BLKS_WRITE)){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fldr_type[fldrn]==FLDR_TYPE_FLH){
|
||||||
|
cyl=blk/(AKAI_FL_DISK_SIDES*AKAI_FLH_DISK_SECTORS);
|
||||||
|
head=1&(blk/AKAI_FLH_DISK_SECTORS);
|
||||||
|
sec=AKAI_FL_SECTOR_BASE+(blk%AKAI_FLH_DISK_SECTORS);
|
||||||
|
}else{
|
||||||
|
cyl=blk/(AKAI_FL_DISK_SIDES*AKAI_FLL_DISK_SECTORS);
|
||||||
|
head=1&(blk/AKAI_FLL_DISK_SECTORS);
|
||||||
|
sec=AKAI_FL_SECTOR_BASE+(blk%AKAI_FLL_DISK_SECTORS);
|
||||||
|
}
|
||||||
|
#ifdef DEBUG
|
||||||
|
PRINTF_OUT("fldr_io_direct: cyl=%u head=%u sec=%u\n",(u_int)cyl,(u_int)head,(u_int)sec);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* check if no floppy inserted */
|
||||||
|
if (!DeviceIoControl(fldr_h[fldrn],IOCTL_FD_CHECK_DISK,NULL,0,NULL,0,&ret,NULL)){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* goto track */
|
||||||
|
if (!DeviceIoControl(fldr_h[fldrn],IOCTL_FDCMD_SEEK,&cyl,sizeof(cyl),NULL,0,&ret,NULL)){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set parameters */
|
||||||
|
rwp.flags=FD_OPTION_MFM;
|
||||||
|
rwp.phead=head;
|
||||||
|
rwp.cyl=cyl;
|
||||||
|
rwp.head=head;
|
||||||
|
rwp.sector=sec;
|
||||||
|
rwp.size=AKAI_FL_SECTOR_SIZE_CODE;
|
||||||
|
rwp.eot=sec+1; /* for IOCTL_FDCMD_READ_DATA,IOCTL_FDCMD_WRITE_DATA: last sector number+1 !!! */
|
||||||
|
rwp.gap=0x0a;
|
||||||
|
rwp.datalen=0xff;
|
||||||
|
|
||||||
|
retval=0; /* no error so far */
|
||||||
|
if (mode==IO_BLKS_WRITE){
|
||||||
|
/* copy sector from buf to DMA buffer */
|
||||||
|
bcopy(buf,(u_char *)fldr_secbuf,AKAI_FL_SECSIZE);
|
||||||
|
|
||||||
|
for (retry=0;retry<FLDR_RETRYMAX;retry++){
|
||||||
|
/* write sector */
|
||||||
|
if (DeviceIoControl(fldr_h[fldrn],IOCTL_FDCMD_WRITE_DATA,&rwp,sizeof(rwp),(PVOID)fldr_secbuf,AKAI_FL_SECSIZE,&ret,NULL)){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (retry>=FLDR_RETRYMAX){
|
||||||
|
retval=-1; /* error */
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
for (retry=0;retry<FLDR_RETRYMAX;retry++){
|
||||||
|
/* read sector */
|
||||||
|
if (DeviceIoControl(fldr_h[fldrn],IOCTL_FDCMD_READ_DATA,&rwp,sizeof(rwp),(PVOID)fldr_secbuf,AKAI_FL_SECSIZE,&ret,NULL)){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (retry>=FLDR_RETRYMAX){
|
||||||
|
retval=-1; /* error */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* copy sector from DMA buffer to buf */
|
||||||
|
/* Note: even if DeviceIoControl() above returned an error */
|
||||||
|
/* in this case, DMA buffer could contain leftover from last call */
|
||||||
|
/* or could contain correct complete or partial sector */
|
||||||
|
/* -> let caller decide what to do with buf in case of an error */
|
||||||
|
bcopy((u_char *)fldr_secbuf,buf,AKAI_FL_SECSIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
fldr_format(int fldrn)
|
||||||
|
{
|
||||||
|
BYTE cyl;
|
||||||
|
BYTE head;
|
||||||
|
BYTE sec;
|
||||||
|
BYTE secnum;
|
||||||
|
BYTE secgap3;
|
||||||
|
BYTE secoffset;
|
||||||
|
BYTE trackskew;
|
||||||
|
DWORD ret;
|
||||||
|
static BYTE fpbuf[sizeof(FD_FORMAT_PARAMS)+sizeof(FD_ID_HEADER)*AKAI_FLH_DISK_SECTORS]; /* space for max. track size */
|
||||||
|
PFD_FORMAT_PARAMS fpp;
|
||||||
|
DWORD fpsize;
|
||||||
|
#ifndef FLDR_FORMAT_NOVERIFY
|
||||||
|
FD_READ_WRITE_PARAMS rwp;
|
||||||
|
#endif
|
||||||
|
u_int retry;
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
if ((fldrn<0)||(fldrn>=FLDRNUM)||(fldr_h[fldrn]==INVALID_HANDLE_VALUE)){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fldr_type[fldrn]==FLDR_TYPE_FLH){
|
||||||
|
secnum=AKAI_FLH_DISK_SECTORS;
|
||||||
|
secgap3=AKAI_FLH_SECTOR_GAP3;
|
||||||
|
secoffset=AKAI_FLH_SECTOR_OFFSET;
|
||||||
|
trackskew=AKAI_FLH_TRACK_SKEW;
|
||||||
|
}else{
|
||||||
|
secnum=AKAI_FLL_DISK_SECTORS;
|
||||||
|
secgap3=AKAI_FLL_SECTOR_GAP3;
|
||||||
|
secoffset=AKAI_FLL_SECTOR_OFFSET;
|
||||||
|
trackskew=AKAI_FLL_TRACK_SKEW;
|
||||||
|
}
|
||||||
|
|
||||||
|
retval=0; /* no error so far */
|
||||||
|
fpp=(PFD_FORMAT_PARAMS)fpbuf;
|
||||||
|
fpsize=sizeof(FD_FORMAT_PARAMS)+secnum*sizeof(FD_ID_HEADER);
|
||||||
|
for (cyl=0;cyl<AKAI_FL_DISK_TRACKS;cyl++){
|
||||||
|
/* check if no floppy inserted */
|
||||||
|
if (!DeviceIoControl(fldr_h[fldrn],IOCTL_FD_CHECK_DISK,NULL,0,NULL,0,&ret,NULL)){
|
||||||
|
PRINTF_OUT("\rno floppy inserted \n",((u_int)cyl)+1);
|
||||||
|
FLUSH_ALL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* goto track */
|
||||||
|
if (!DeviceIoControl(fldr_h[fldrn],IOCTL_FDCMD_SEEK,&cyl,sizeof(cyl),NULL,0,&ret,NULL)){
|
||||||
|
PRINTF_OUT("\rtrack %u - cannot seek track\n",((u_int)cyl)+1);
|
||||||
|
FLUSH_ALL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (head=0;head<AKAI_FL_DISK_SIDES;head++){
|
||||||
|
PRINTF_OUT("\rtrack %u side %u",((u_int)cyl)+1,((u_int)head)+1);
|
||||||
|
FLUSH_ALL;
|
||||||
|
|
||||||
|
/* set parameters */
|
||||||
|
fpp->flags=FD_OPTION_MFM;
|
||||||
|
fpp->phead=head;
|
||||||
|
fpp->size=AKAI_FL_SECTOR_SIZE_CODE;
|
||||||
|
fpp->sectors=secnum;
|
||||||
|
fpp->gap=secgap3;
|
||||||
|
fpp->fill=AKAI_FL_SECTOR_FILL;
|
||||||
|
for (sec=0;sec<secnum;sec++){
|
||||||
|
fpp->Header[sec].cyl=cyl;
|
||||||
|
fpp->Header[sec].head=head;
|
||||||
|
fpp->Header[sec].sector=AKAI_FL_SECTOR_BASE+((secoffset+sec+cyl*(secnum-trackskew))%secnum);
|
||||||
|
fpp->Header[sec].size=AKAI_FL_SECTOR_SIZE_CODE;
|
||||||
|
}
|
||||||
|
#ifndef FLDR_FORMAT_NOVERIFY
|
||||||
|
rwp.flags=FD_OPTION_MFM;
|
||||||
|
rwp.phead=head;
|
||||||
|
rwp.cyl=cyl;
|
||||||
|
rwp.head=head;
|
||||||
|
rwp.sector=AKAI_FL_SECTOR_BASE;
|
||||||
|
rwp.size=AKAI_FL_SECTOR_SIZE_CODE;
|
||||||
|
rwp.eot=AKAI_FL_SECTOR_BASE+secnum-1; /* for IOCTL_FDCMD_VERIFY: last sector number !!! */
|
||||||
|
rwp.gap=0x0a;
|
||||||
|
rwp.datalen=0xff;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (retry=0;retry<FLDR_RETRYMAX;retry++){
|
||||||
|
/* format track */
|
||||||
|
if (DeviceIoControl(fldr_h[fldrn],IOCTL_FDCMD_FORMAT_TRACK,fpp,fpsize,NULL,0,&ret,NULL)){
|
||||||
|
#ifndef FLDR_FORMAT_NOVERIFY
|
||||||
|
/* verify track */
|
||||||
|
if (DeviceIoControl(fldr_h[fldrn],IOCTL_FDCMD_VERIFY,&rwp,sizeof(rwp),NULL,0,&ret,NULL))
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (retry>=FLDR_RETRYMAX){
|
||||||
|
PRINTF_OUT(" - cannot format track\n");
|
||||||
|
FLUSH_ALL;
|
||||||
|
#if 1
|
||||||
|
/* XXX ignore error, continue */
|
||||||
|
retval=-1;
|
||||||
|
#else
|
||||||
|
return -1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PRINTF_OUT("\rdone \n");
|
||||||
|
FLUSH_ALL;
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
#endif /* _VISUALCPP */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* cache */
|
||||||
|
|
||||||
|
struct blk_cache_s blk_cache[BLK_CACHE_NUM];
|
||||||
|
int blk_cache_enable;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
init_blk_cache(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i=0;i<BLK_CACHE_NUM;i++){
|
||||||
|
blk_cache[i].valid=0; /* free entry */
|
||||||
|
blk_cache[i].buf=NULL; /* not allocated yet */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
free_blk_cache(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i=0;i<BLK_CACHE_NUM;i++){
|
||||||
|
if (blk_cache[i].buf!=NULL){ /* buffer allocated? */
|
||||||
|
/* free buffer */
|
||||||
|
free(blk_cache[i].buf);
|
||||||
|
blk_cache[i].valid=0; /* free entry */
|
||||||
|
blk_cache[i].buf=NULL; /* not allocated yet */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
print_blk_cache(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
#ifdef _VISUALCPP
|
||||||
|
PRINTF_OUT("nr fd fldrn start/B blksize blk age mod\n");
|
||||||
|
PRINTF_OUT("--------------------------------------------------------------\n");
|
||||||
|
#else /* !_VISUALCPP */
|
||||||
|
PRINTF_OUT("nr fd start/B blksize blk age mod\n");
|
||||||
|
PRINTF_OUT("--------------------------------------------------------\n");
|
||||||
|
#endif /* !_VISUALCPP */
|
||||||
|
for (i=0;i<BLK_CACHE_NUM;i++){
|
||||||
|
if (!blk_cache[i].valid){ /* free entry? */
|
||||||
|
continue; /* next */
|
||||||
|
}
|
||||||
|
#ifdef _VISUALCPP
|
||||||
|
PRINTF_OUT("%4i %3i %3i 0x%02x%08x 0x%04x 0x%04x 0x%08x %i\n",
|
||||||
|
i,
|
||||||
|
blk_cache[i].fd,
|
||||||
|
blk_cache[i].fldrn,
|
||||||
|
(u_int)(blk_cache[i].startoff>>32),
|
||||||
|
(u_int)(0xffffffff&blk_cache[i].startoff),
|
||||||
|
blk_cache[i].blksize,
|
||||||
|
blk_cache[i].blk,
|
||||||
|
blk_cache[i].age,
|
||||||
|
blk_cache[i].modified);
|
||||||
|
#else /* !_VISUALCPP */
|
||||||
|
PRINTF_OUT("%4i %3i 0x%02x%08x 0x%04x 0x%04x 0x%08x %i\n",
|
||||||
|
i,
|
||||||
|
blk_cache[i].fd,
|
||||||
|
(u_int)(blk_cache[i].startoff>>32),
|
||||||
|
(u_int)(0xffffffff&blk_cache[i].startoff),
|
||||||
|
blk_cache[i].blksize,
|
||||||
|
blk_cache[i].blk,
|
||||||
|
blk_cache[i].age,
|
||||||
|
blk_cache[i].modified);
|
||||||
|
#endif /* !_VISUALCPP */
|
||||||
|
}
|
||||||
|
#ifdef _VISUALCPP
|
||||||
|
PRINTF_OUT("--------------------------------------------------------------\n");
|
||||||
|
#else /* !_VISUALCPP */
|
||||||
|
PRINTF_OUT("--------------------------------------------------------\n");
|
||||||
|
#endif /* !_VISUALCPP */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
find_blk_cache(int fd,
|
||||||
|
#ifdef _VISUALCPP
|
||||||
|
int fldrn,
|
||||||
|
#endif /* _VISUALCPP */
|
||||||
|
OFF64_T startoff,u_int blk,u_int blksize)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* scan cache */
|
||||||
|
for (i=0;i<BLK_CACHE_NUM;i++){
|
||||||
|
if (blk_cache[i].buf==NULL){
|
||||||
|
continue; /* next */
|
||||||
|
}
|
||||||
|
if (!blk_cache[i].valid){ /* free? */
|
||||||
|
continue; /* next */
|
||||||
|
}
|
||||||
|
/* check if contained within cache */
|
||||||
|
/* Note: must check for blksize as well!!! */
|
||||||
|
if ((fd==blk_cache[i].fd)
|
||||||
|
#ifdef _VISUALCPP
|
||||||
|
&&(fldrn==blk_cache[i].fldrn)
|
||||||
|
#endif /* _VISUALCPP */
|
||||||
|
&&(startoff==blk_cache[i].startoff)
|
||||||
|
&&(blk==blk_cache[i].blk)
|
||||||
|
&&(blksize==blk_cache[i].blksize)){
|
||||||
|
break; /* found it */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i==BLK_CACHE_NUM){ /* none found? */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
blk_cache_aging(int i)
|
||||||
|
{
|
||||||
|
int j;
|
||||||
|
u_int agemin;
|
||||||
|
|
||||||
|
if ((i<0)||(i>=BLK_CACHE_NUM)||(!blk_cache[i].valid)){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
blk_cache[i].age=0; /* reset age */
|
||||||
|
|
||||||
|
/* find the youngest of the others */
|
||||||
|
agemin=BLK_CACHE_AGE_MAX;
|
||||||
|
for (j=0;j<BLK_CACHE_NUM;j++){
|
||||||
|
if (!blk_cache[j].valid){ /* free? */
|
||||||
|
continue; /* next */
|
||||||
|
}
|
||||||
|
if (j==i){
|
||||||
|
continue; /* next */
|
||||||
|
}
|
||||||
|
if (blk_cache[j].age<agemin){
|
||||||
|
agemin=blk_cache[j].age;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (agemin==0){ /* somebody else too young? */
|
||||||
|
/* increment age of the others */
|
||||||
|
for (j=0;j<BLK_CACHE_NUM;j++){
|
||||||
|
if (j==i){
|
||||||
|
continue; /* next */
|
||||||
|
}
|
||||||
|
if (blk_cache[j].age<BLK_CACHE_AGE_MAX){
|
||||||
|
blk_cache[j].age++; /* increase age */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
io_blks_direct(int fd,
|
||||||
|
#ifdef _VISUALCPP
|
||||||
|
int fldrn,
|
||||||
|
#endif /* _VISUALCPP */
|
||||||
|
OFF64_T startoff,u_char *buf,u_int bstart,u_int bsize,u_int blksize,int cachealloc,int mode)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
int j,jmax;
|
||||||
|
u_int agemax;
|
||||||
|
u_int blk,blkmin,blkmax,blkchunk;
|
||||||
|
|
||||||
|
if (buf==NULL){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#ifdef _VISUALCPP
|
||||||
|
if ((fd<0)&&(fldrn<0)){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#else /* !_VISUALCPP */
|
||||||
|
if (fd<0){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif /* !_VISUALCPP */
|
||||||
|
|
||||||
|
if ((mode!=IO_BLKS_READ)&&(mode!=IO_BLKS_WRITE)){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Note: OFF64_T against overflow */
|
||||||
|
if ((((OFF64_T)bstart)+((OFF64_T)bsize))>(OFF64_T)0xffffffff){ /* XXX */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bsize==0){
|
||||||
|
return 0; /* done */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!blk_cache_enable){ /* cache disabled? */
|
||||||
|
cachealloc=0; /* don't allocate cache */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cachealloc /* must allocate cache? */
|
||||||
|
#ifdef _VISUALCPP
|
||||||
|
||(fldrn>=0) /* or is floppy drive? */
|
||||||
|
#endif /* _VISUALCPP */
|
||||||
|
){
|
||||||
|
/* single blocks */
|
||||||
|
blkmin=bstart;
|
||||||
|
blkmax=bstart+bsize;
|
||||||
|
blkchunk=1;
|
||||||
|
}else{
|
||||||
|
/* all blocks at once */
|
||||||
|
blkmin=bstart;
|
||||||
|
blkmax=bstart+1; /* fake value: only once */
|
||||||
|
blkchunk=bsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (blk=blkmin;blk<blkmax;blk++){
|
||||||
|
#ifdef _VISUALCPP
|
||||||
|
if (fldrn>=0){ /* is floppy drive? */
|
||||||
|
/* Note: ignore startoff if floppy drive */
|
||||||
|
if (fldr_io_direct(fldrn,blk,buf+(blk-blkmin)*blksize,mode)<0){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}else /* no floppy drive */
|
||||||
|
#endif /* _VISUALCPP */
|
||||||
|
{
|
||||||
|
/* goto blk */
|
||||||
|
if (LSEEK64(fd,startoff+(OFF64_T)(blk*blksize),SEEK_SET)<0){
|
||||||
|
#ifdef DEBUG
|
||||||
|
PERROR("lseek");
|
||||||
|
#endif
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (mode==IO_BLKS_WRITE){
|
||||||
|
/* write block(s) */
|
||||||
|
err=WRITE(fd,(void *)(buf+(blk-blkmin)*blksize),blkchunk*blksize);
|
||||||
|
if (err<0){
|
||||||
|
#ifdef DEBUG
|
||||||
|
PERROR("write");
|
||||||
|
#endif
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (err!=(int)(blkchunk*blksize)){
|
||||||
|
#ifdef DEBUG
|
||||||
|
PRINTF_ERR("write: incomplete\n");
|
||||||
|
#endif
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
/* read block(s) */
|
||||||
|
err=READ(fd,(void *)(buf+(blk-blkmin)*blksize),blkchunk*blksize);
|
||||||
|
if (err<0){
|
||||||
|
#ifdef DEBUG
|
||||||
|
PERROR("read");
|
||||||
|
#endif
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (err!=(int)(blkchunk*blksize)){
|
||||||
|
#ifdef DEBUG
|
||||||
|
PRINTF_ERR("read: incomplete\n");
|
||||||
|
#endif
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (cachealloc){ /* must allocate cache? */
|
||||||
|
/* find free entry or the oldest one */
|
||||||
|
agemax=0;
|
||||||
|
jmax=0; /* first guess */
|
||||||
|
for (j=0;j<BLK_CACHE_NUM;j++){
|
||||||
|
if (!blk_cache[j].valid){ /* free? */
|
||||||
|
jmax=j;
|
||||||
|
break; /* found one */
|
||||||
|
}
|
||||||
|
if (blk_cache[j].age>=agemax){ /* older or equal? */
|
||||||
|
agemax=blk_cache[j].age;
|
||||||
|
jmax=j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* old cache entry not free and modified? */
|
||||||
|
err=0;
|
||||||
|
if ((blk_cache[jmax].valid)&&(blk_cache[jmax].modified)&&(blk_cache[jmax].buf!=NULL)){
|
||||||
|
/* must flush this block */
|
||||||
|
if (io_blks_direct(blk_cache[jmax].fd,
|
||||||
|
#ifdef _VISUALCPP
|
||||||
|
blk_cache[jmax].fldrn,
|
||||||
|
#endif /* _VISUALCPP */
|
||||||
|
blk_cache[jmax].startoff,
|
||||||
|
(u_char *)blk_cache[jmax].buf,
|
||||||
|
blk_cache[jmax].blk,
|
||||||
|
1,
|
||||||
|
blk_cache[jmax].blksize,
|
||||||
|
0, /* don't alloc cache */
|
||||||
|
IO_BLKS_WRITE)<0){
|
||||||
|
PRINTF_ERR("cannot flush cache block 0x%08x of fd %i\n",blk_cache[jmax].blk,blk_cache[jmax].fd);
|
||||||
|
err=1; /* cannot allocate below */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!err){
|
||||||
|
if ((blk_cache[jmax].buf!=NULL)&&(blk_cache[jmax].blksize!=blksize)){ /* not compatible? */
|
||||||
|
/* free buffer */
|
||||||
|
free(blk_cache[jmax].buf);
|
||||||
|
blk_cache[jmax].buf=NULL;
|
||||||
|
}
|
||||||
|
if (blk_cache[jmax].buf==NULL){ /* buffer not allocated yet/anymore? */
|
||||||
|
/* need to allocate buffer */
|
||||||
|
if ((blk_cache[jmax].buf=(u_char *)malloc(blksize))==NULL){
|
||||||
|
PERROR("malloc");
|
||||||
|
err=1; /* cannot allocate below */
|
||||||
|
}
|
||||||
|
blk_cache[jmax].valid=0; /* free */
|
||||||
|
blk_cache[jmax].blksize=blksize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!err){
|
||||||
|
/* allocate cache entry */
|
||||||
|
blk_cache[jmax].valid=1;
|
||||||
|
blk_cache[jmax].modified=0;
|
||||||
|
blk_cache[jmax].fd=fd;
|
||||||
|
#ifdef _VISUALCPP
|
||||||
|
blk_cache[jmax].fldrn=fldrn;
|
||||||
|
#endif /* _VISUALCPP */
|
||||||
|
blk_cache[jmax].startoff=startoff;
|
||||||
|
blk_cache[jmax].blk=blk;
|
||||||
|
blk_cache_aging(jmax); /* adjust ages */
|
||||||
|
/* copy data */
|
||||||
|
bcopy(buf+(blk-blkmin)*blksize,blk_cache[jmax].buf,blksize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Note: prior to changing blksize of any device/file, must flush cache first !!! */
|
||||||
|
int
|
||||||
|
flush_blk_cache(void)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* scan cache */
|
||||||
|
ret=0; /* no error so far */
|
||||||
|
for (i=0;i<BLK_CACHE_NUM;i++){
|
||||||
|
if (blk_cache[i].buf==NULL){
|
||||||
|
continue; /* next */
|
||||||
|
}
|
||||||
|
if (!blk_cache[i].valid){ /* free? */
|
||||||
|
continue; /* next */
|
||||||
|
}
|
||||||
|
if (!blk_cache[i].modified){ /* not modified? */
|
||||||
|
continue; /* next */
|
||||||
|
}
|
||||||
|
/* must write */
|
||||||
|
if (io_blks_direct(blk_cache[i].fd,
|
||||||
|
#ifdef _VISUALCPP
|
||||||
|
blk_cache[i].fldrn,
|
||||||
|
#endif /* _VISUALCPP */
|
||||||
|
blk_cache[i].startoff,
|
||||||
|
(u_char *)blk_cache[i].buf,
|
||||||
|
blk_cache[i].blk,
|
||||||
|
1,
|
||||||
|
blk_cache[i].blksize,
|
||||||
|
0, /* don't alloc cache */
|
||||||
|
IO_BLKS_WRITE)<0){
|
||||||
|
PRINTF_ERR("cannot flush cache block 0x%08x of fd %i\n",blk_cache[i].blk,blk_cache[i].fd);
|
||||||
|
/* XXX cannot do more now, maybe more luck next time */
|
||||||
|
ret=-1;
|
||||||
|
}else{
|
||||||
|
blk_cache[i].modified=0; /* done */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
io_blks(int fd,
|
||||||
|
#ifdef _VISUALCPP
|
||||||
|
int fldrn,
|
||||||
|
#endif /* _VISUALCPP */
|
||||||
|
OFF64_T startoff,u_char *buf,u_int bstart,u_int bsize,u_int blksize,int cachealloc,int mode)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
u_int blk;
|
||||||
|
u_int chunkstart,chunksize;
|
||||||
|
|
||||||
|
if (buf==NULL){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((mode!=IO_BLKS_READ)&&(mode!=IO_BLKS_WRITE)){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Note: OFF64_T against overflow */
|
||||||
|
if ((((OFF64_T)bstart)+((OFF64_T)bsize))>(OFF64_T)0xffffffff){ /* XXX */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#ifdef _VISUALCPP
|
||||||
|
if ((fd<0)&&(fldrn<0)){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#else /* !_VISUALCPP */
|
||||||
|
if (fd<0){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif /* !_VISUALCPP */
|
||||||
|
|
||||||
|
if (!blk_cache_enable){ /* cache disabled? */
|
||||||
|
cachealloc=0; /* don't allocate cache */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check every block */
|
||||||
|
chunkstart=bstart;
|
||||||
|
chunksize=0; /* no chunk of missing blocks so far */
|
||||||
|
for (blk=bstart;blk<(bstart+bsize);blk++){
|
||||||
|
if (blk_cache_enable){ /* cache enabled? */
|
||||||
|
/* look in cache */
|
||||||
|
i=find_blk_cache(fd,
|
||||||
|
#ifdef _VISUALCPP
|
||||||
|
fldrn,
|
||||||
|
#endif /* _VISUALCPP */
|
||||||
|
startoff,blk,blksize);
|
||||||
|
/* Note: no match for blk if blksize has changed!!! */
|
||||||
|
/* however, these cache entries can be reused if needed */
|
||||||
|
}else{
|
||||||
|
i=-1; /* not found in cache */
|
||||||
|
}
|
||||||
|
if (i<0){ /* not found in cache? */
|
||||||
|
if (chunksize==0){ /* new chunk of missing blocks? */
|
||||||
|
chunkstart=blk; /* start of chunk */
|
||||||
|
}
|
||||||
|
chunksize++; /* one more missing block */
|
||||||
|
}else{
|
||||||
|
/* found in cache */
|
||||||
|
/* Note: now, blk_cache[i].buf!=NULL */
|
||||||
|
|
||||||
|
/* Note: must do cache-I/O first, since io_blks_direct could steal i from cache */
|
||||||
|
if (mode==IO_BLKS_WRITE){
|
||||||
|
/* copy to cache */
|
||||||
|
bcopy(buf+(blk-bstart)*blksize,blk_cache[i].buf,blksize);
|
||||||
|
blk_cache[i].modified=1; /* modified */
|
||||||
|
}else{
|
||||||
|
/* copy from cache */
|
||||||
|
bcopy(blk_cache[i].buf,buf+(blk-bstart)*blksize,blksize);
|
||||||
|
}
|
||||||
|
blk_cache_aging(i); /* adjust ages */
|
||||||
|
|
||||||
|
/* chunk of missing blocks pending? */
|
||||||
|
if (chunksize>0){
|
||||||
|
/* must read or write */
|
||||||
|
if (io_blks_direct(fd,
|
||||||
|
#ifdef _VISUALCPP
|
||||||
|
fldrn,
|
||||||
|
#endif /* _VISUALCPP */
|
||||||
|
startoff,
|
||||||
|
(u_char *)(buf+(chunkstart-bstart)*blksize),
|
||||||
|
chunkstart,
|
||||||
|
chunksize,
|
||||||
|
blksize,
|
||||||
|
cachealloc,
|
||||||
|
mode)<0){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
chunksize=0; /* no chunk of missing blocks anymore */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* one last time: chunk of missing blocks pending? */
|
||||||
|
if (chunksize>0){
|
||||||
|
/* must read or write */
|
||||||
|
if (io_blks_direct(fd,
|
||||||
|
#ifdef _VISUALCPP
|
||||||
|
fldrn,
|
||||||
|
#endif /* _VISUALCPP */
|
||||||
|
startoff,
|
||||||
|
(u_char *)(buf+(chunkstart-bstart)*blksize),
|
||||||
|
chunkstart,
|
||||||
|
chunksize,
|
||||||
|
blksize,
|
||||||
|
cachealloc,
|
||||||
|
mode)<0){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
chunksize=0; /* no chunk of missing blocks anymore */
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* EOF */
|
||||||
+137
@@ -0,0 +1,137 @@
|
|||||||
|
#ifndef __AKAIUTIL_IO_H
|
||||||
|
#define __AKAIUTIL_IO_H
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2008,2010,2012,2019,2020,2021 Klaus Michael Indlekofer. All rights reserved.
|
||||||
|
*
|
||||||
|
* m.indlekofer@gmx.de
|
||||||
|
*
|
||||||
|
* This program 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 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include "commoninclude.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef _VISUALCPP
|
||||||
|
/* for low-level floppy I/O, using fdrawcmd.sys */
|
||||||
|
#include "fdrawcmd.h" /* from http://simonowen.com/fdrawcmd/fdrawcmd.h */
|
||||||
|
|
||||||
|
/* definitions for low-level format of floppy disks for AKAI samplers */
|
||||||
|
#define AKAI_FL_DISK_SIDES 2 /* sides per disk */
|
||||||
|
#define AKAI_FL_DISK_TRACKS 80 /* tracks per side */
|
||||||
|
#define AKAI_FLL_DISK_SECTORS 5 /* sectors per track for low-density floppy */
|
||||||
|
#define AKAI_FLH_DISK_SECTORS 10 /* sectors per track for high-density floppy */
|
||||||
|
#define AKAI_FLL_DISK_DATARATE FD_RATE_250K /* data rate for low-density floppy */
|
||||||
|
#define AKAI_FLH_DISK_DATARATE FD_RATE_500K /* data rate for high-density floppy */
|
||||||
|
#define AKAI_FL_SECTOR_SIZE_CODE 3 /* sector size code: 3 -> (128<<3)==1024 */
|
||||||
|
#define AKAI_FLL_SECTOR_GAP3 0x74 /* gap3 size between sectors for low-density floppy */
|
||||||
|
#define AKAI_FLH_SECTOR_GAP3 0x74 /* gap3 size between sectors for high-density floppy */
|
||||||
|
#define AKAI_FL_SECTOR_FILL 0x00 /* fill byte for formatted sectors */
|
||||||
|
#define AKAI_FL_SECTOR_BASE 1 /* first sector number on track */
|
||||||
|
#define AKAI_FLL_SECTOR_OFFSET 3 /* sector number offset for low-density floppy */
|
||||||
|
#define AKAI_FLH_SECTOR_OFFSET 6 /* sector number offset for high-density floppy */
|
||||||
|
#define AKAI_FLL_TRACK_SKEW 2 /* skew to the same sector on the next track for low-density floppy */
|
||||||
|
#define AKAI_FLH_TRACK_SKEW 4 /* skew to the same sector on the next track for high-density floppy */
|
||||||
|
|
||||||
|
/* low-level floppy sector size */
|
||||||
|
#define AKAI_FL_SECSIZE 0x0400 /* 1KB */
|
||||||
|
/* Note: must be == AKAI_FL_BLOCKSIZE (floppy filesystem blocksize, defined in akaiutil.h) */
|
||||||
|
#if defined(AKAI_FL_BLOCKSIZE)&&(AKAI_FL_SECSIZE!=AKAI_FL_BLOCKSIZE)
|
||||||
|
#error "AKAI_FL_SECSIZE!=AKAI_FL_BLOCKSIZE"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef FLDRNUM
|
||||||
|
#define FLDRNUM 2 /* XXX max. number of floppy drives */
|
||||||
|
#endif
|
||||||
|
extern HANDLE fldr_h[FLDRNUM]; /* handle for floppy drive */
|
||||||
|
#define FLDR_TYPE_FLL 0 /* low-density floppy */
|
||||||
|
#define FLDR_TYPE_FLH 1 /* high-density floppy */
|
||||||
|
extern u_int fldr_type[FLDRNUM]; /* floppy drive type */
|
||||||
|
extern PBYTE fldr_secbuf; /* DMA buffer for sector */
|
||||||
|
|
||||||
|
#ifndef FLDR_RETRYMAX
|
||||||
|
#define FLDR_RETRYMAX 5 /* XXX max. number of retries for floppy I/O */
|
||||||
|
#endif
|
||||||
|
#endif /* _VISUALCPP */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* cache */
|
||||||
|
|
||||||
|
struct blk_cache_s{
|
||||||
|
int valid;
|
||||||
|
int modified;
|
||||||
|
int fd;
|
||||||
|
#ifdef _VISUALCPP
|
||||||
|
int fldrn;
|
||||||
|
#endif /* _VISUALCPP */
|
||||||
|
OFF64_T startoff;
|
||||||
|
u_int blk;
|
||||||
|
u_int blksize;
|
||||||
|
#define BLK_CACHE_AGE_MAX 0xffffffff /* XXX max. age */
|
||||||
|
u_int age; /* age */
|
||||||
|
u_char *buf;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifndef BLK_CACHE_NUM
|
||||||
|
#define BLK_CACHE_NUM 512 /* XXX */
|
||||||
|
#endif
|
||||||
|
extern struct blk_cache_s blk_cache[BLK_CACHE_NUM];
|
||||||
|
|
||||||
|
extern int blk_cache_enable;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define IO_BLKS_READ 0
|
||||||
|
#define IO_BLKS_WRITE 1
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Declarations */
|
||||||
|
|
||||||
|
#ifdef _VISUALCPP
|
||||||
|
extern int fldr_init(void);
|
||||||
|
extern void fldr_end(void);
|
||||||
|
extern int fldr_open(int fldrn,u_int fldrtype);
|
||||||
|
extern int fldr_checkfloppyinserted(int fldrn);
|
||||||
|
extern int fldr_io_direct(int fldrn,u_int blk,u_char *buf,int mode);
|
||||||
|
extern int fldr_format(int fldrn);
|
||||||
|
#endif /* _VISUALCPP */
|
||||||
|
extern void init_blk_cache(void);
|
||||||
|
extern void free_blk_cache(void);
|
||||||
|
extern void print_blk_cache(void);
|
||||||
|
extern int find_blk_cache(int fd,
|
||||||
|
#ifdef _VISUALCPP
|
||||||
|
int fldrnr,
|
||||||
|
#endif
|
||||||
|
OFF64_T startoff,u_int blk,u_int blksize);
|
||||||
|
extern void blk_cache_aging(int i);
|
||||||
|
extern int io_blks_direct(int fd,
|
||||||
|
#ifdef _VISUALCPP
|
||||||
|
int fldrn,
|
||||||
|
#endif
|
||||||
|
OFF64_T startoff,u_char *buf,u_int bstart,u_int bsize,u_int blksize,int cachealloc,int mode);
|
||||||
|
extern int flush_blk_cache(void);
|
||||||
|
extern int io_blks(int fd,
|
||||||
|
#ifdef _VISUALCPP
|
||||||
|
int fldrn,
|
||||||
|
#endif
|
||||||
|
OFF64_T startoff,u_char *buf,u_int bstart,u_int bsize,u_int blksize,int cachealloc,int mode);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* !__AKAIUTIL_IO_H */
|
||||||
+5651
File diff suppressed because it is too large
Load Diff
+1040
File diff suppressed because it is too large
Load Diff
+68
@@ -0,0 +1,68 @@
|
|||||||
|
#ifndef __AKAIUTIL_TAKE_H
|
||||||
|
#define __AKAIUTIL_TAKE_H
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2012,2018,2019 Klaus Michael Indlekofer. All rights reserved.
|
||||||
|
*
|
||||||
|
* m.indlekofer@gmx.de
|
||||||
|
*
|
||||||
|
* This program 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 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include "commoninclude.h"
|
||||||
|
#include "akaiutil.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* AKAI DD takes */
|
||||||
|
|
||||||
|
/* Note: all data types are little endian */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* S1100/S3000 DD take header (directory entry in DD partition header) */
|
||||||
|
/* XXX should be defined in akaiutil_take.h, but must be in akaiutil.h due to dependencies */
|
||||||
|
struct akai_ddtake_s;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* file name ending for exported DD take */
|
||||||
|
#define AKAI_DDTAKE_FNAMEEND ".TK"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Declarations */
|
||||||
|
|
||||||
|
extern int akai_ddtake_info(struct part_s *pp,u_int ti,int verbose);
|
||||||
|
|
||||||
|
extern int akai_import_take(int inpfd,struct part_s *pp,struct akai_ddtake_s *tp,u_int ti,u_int csizes,u_int csizee);
|
||||||
|
|
||||||
|
extern int akai_export_take(int outfd,struct part_s *pp,struct akai_ddtake_s *tp,u_int csizes,u_int csizee,u_int cstarts,u_int cstarte);
|
||||||
|
|
||||||
|
#define TAKE2WAV_CHECK 1
|
||||||
|
#define TAKE2WAV_EXPORT 2
|
||||||
|
#define TAKE2WAV_CREATE 4
|
||||||
|
#define TAKE2WAV_ALL 0xff
|
||||||
|
extern int akai_take2wav(struct part_s *pp,u_int ti,int wavfd,u_int *sizep,char **wavnamep,int what);
|
||||||
|
|
||||||
|
#define WAV2TAKE_OPEN 1
|
||||||
|
extern int akai_wav2take(int wavfd,char *wavname,struct part_s *pp,u_int ti,u_int *bcountp,int what);
|
||||||
|
|
||||||
|
extern int akai_take_setenv(struct part_s *pp,u_int cstarts,u_int samplesize,u_char *envbuf,u_int envsiz);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* !__AKAIUTIL_TAKE_H */
|
||||||
+1235
File diff suppressed because it is too large
Load Diff
+95
@@ -0,0 +1,95 @@
|
|||||||
|
#ifndef __AKAIUTIL_TAR_H
|
||||||
|
#define __AKAIUTIL_TAR_H
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2008,2010,2012,2019,2021 Klaus Michael Indlekofer. All rights reserved.
|
||||||
|
*
|
||||||
|
* m.indlekofer@gmx.de
|
||||||
|
*
|
||||||
|
* This program 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 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include "commoninclude.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* tar header */
|
||||||
|
|
||||||
|
/* Note: numbers in octal, trailing '\0' */
|
||||||
|
struct tar_head_s{
|
||||||
|
#define TAR_NAMELEN 100 /* incl. '\0' */
|
||||||
|
char name[TAR_NAMELEN];
|
||||||
|
char mode[8];
|
||||||
|
char uid[8];
|
||||||
|
char gid[8];
|
||||||
|
char size[12];
|
||||||
|
char mtime[12];
|
||||||
|
char chksum[7];
|
||||||
|
char space;
|
||||||
|
char type;
|
||||||
|
char linkname[TAR_NAMELEN];
|
||||||
|
#define TAR_USTAR "ustar\00000"
|
||||||
|
char ustar[8];
|
||||||
|
char uname[32];
|
||||||
|
char gname[32];
|
||||||
|
char devmajor[8];
|
||||||
|
char devminor[8];
|
||||||
|
#define TAR_PREFIXLEN 155 /* incl. '\0' */
|
||||||
|
char prefix[TAR_PREFIXLEN];
|
||||||
|
char zero[12];
|
||||||
|
};
|
||||||
|
/* should be 512 bytes */
|
||||||
|
#define TAR_BLOCKSIZE 512 /* in bytes */
|
||||||
|
|
||||||
|
#define TAR_TYPE_REG '0' /* regular file */
|
||||||
|
#define TAR_TYPE_REG0 '\0' /* regular file */
|
||||||
|
#define TAR_TYPE_DIR '5' /* directory */
|
||||||
|
|
||||||
|
#define TAR_TAILZERO_BLOCKS 6 /* number or zero blocks at file end */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Declarations */
|
||||||
|
|
||||||
|
extern u_int tar_checksum(u_char *hp);
|
||||||
|
|
||||||
|
#define TAR_EXPORT_DISK 0x0001
|
||||||
|
#define TAR_EXPORT_PART 0x0002
|
||||||
|
#define TAR_EXPORT_VOL 0x0004
|
||||||
|
#define TAR_EXPORT_FILE 0x0008
|
||||||
|
#define TAR_EXPORT_DDFILE 0x0010
|
||||||
|
#define TAR_EXPORT_TAGSFILE 0x0020
|
||||||
|
#define TAR_EXPORT_VOLPARAMFILE 0x0040
|
||||||
|
#define TAR_EXPORT_ANYFILE (TAR_EXPORT_FILE|TAR_EXPORT_DDFILE|TAR_EXPORT_TAGSFILE|TAR_EXPORT_VOLPARAMFILE)
|
||||||
|
#define TAR_EXPORT_WAV 0x1000
|
||||||
|
extern int tar_export(int fd,struct disk_s *dp,struct part_s *pp,struct vol_s *vp,struct file_s *fp,u_int ti,u_int flags,int verbose,u_char *filtertagp);
|
||||||
|
extern int tar_export_vol(int fd,struct vol_s *vp,u_int flags,int verbose,u_char *filtertagp);
|
||||||
|
extern int tar_export_part(int fd,struct part_s *pp,u_int flags,int verbose,u_char *filtertagp);
|
||||||
|
extern int tar_export_disk(int fd,struct disk_s *dp,u_int flags,int verbose,u_char *filtertagp);
|
||||||
|
extern int tar_export_alldisks(int fd,u_int flags,int verbose,u_char *filtertagp);
|
||||||
|
extern int tar_export_curdir(int fd,int verbose,u_int flags);
|
||||||
|
extern int tar_export_tailzero(int fd);
|
||||||
|
|
||||||
|
#define TAR_IMPORT_WAV 0x0100
|
||||||
|
#define TAR_IMPORT_WAVS9 0x1000
|
||||||
|
#define TAR_IMPORT_WAVS9C 0x2000
|
||||||
|
#define TAR_IMPORT_WAVS1 0x4000
|
||||||
|
#define TAR_IMPORT_WAVS3 0x8000
|
||||||
|
extern int tar_import_curdir(int fd,u_int vtype0,int verbose,u_int flags);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* !__AKAIUTIL_TAR_H */
|
||||||
+482
@@ -0,0 +1,482 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2010,2019 Klaus Michael Indlekofer. All rights reserved.
|
||||||
|
*
|
||||||
|
* m.indlekofer@gmx.de
|
||||||
|
*
|
||||||
|
* This program 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 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include "commoninclude.h"
|
||||||
|
#include "akaiutil_wav.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
wav_write_head(int outdes,
|
||||||
|
u_int datasize,u_int chnr,u_int samprate,u_int bitnr,
|
||||||
|
u_int extrasize)
|
||||||
|
{
|
||||||
|
struct wav_riffhead_s wavriffhead;
|
||||||
|
struct wav_chunkhead_s wavchunkhead;
|
||||||
|
struct wav_fmthead_s wavfmthead;
|
||||||
|
u_int drate;
|
||||||
|
|
||||||
|
/* create WAVE RIFF header */
|
||||||
|
bzero(&wavriffhead,sizeof(struct wav_riffhead_s));
|
||||||
|
bcopy(WAV_RIFFHEAD_RIFFSTR,wavriffhead.riffstr,4);
|
||||||
|
{
|
||||||
|
u_int fsize;
|
||||||
|
|
||||||
|
fsize=WAV_HEAD_SIZE-sizeof(struct wav_chunkhead_s)+datasize+extrasize;
|
||||||
|
wavriffhead.fsize[0]=0xff&fsize;
|
||||||
|
wavriffhead.fsize[1]=0xff&(fsize>>8);
|
||||||
|
wavriffhead.fsize[2]=0xff&(fsize>>16);
|
||||||
|
wavriffhead.fsize[3]=0xff&(fsize>>24);
|
||||||
|
}
|
||||||
|
bcopy(WAV_RIFFHEAD_WAVESTR,wavriffhead.wavestr,4);
|
||||||
|
|
||||||
|
/* write WAVE RIFF header */
|
||||||
|
if (WRITE(outdes,&wavriffhead,sizeof(struct wav_riffhead_s))!=sizeof(struct wav_riffhead_s)){
|
||||||
|
PRINTF_ERR("cannot write WAVE RIFF header\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* create FMT chunk header */
|
||||||
|
bcopy(WAV_CHUNKHEAD_FMTSTR,wavchunkhead.typestr,4);
|
||||||
|
{
|
||||||
|
u_int csize;
|
||||||
|
|
||||||
|
csize=sizeof(struct wav_fmthead_s);
|
||||||
|
wavchunkhead.csize[0]=0xff&csize;
|
||||||
|
wavchunkhead.csize[1]=0xff&(csize>>8);
|
||||||
|
wavchunkhead.csize[2]=0xff&(csize>>16);
|
||||||
|
wavchunkhead.csize[3]=0xff&(csize>>24);
|
||||||
|
}
|
||||||
|
/* write chunk header */
|
||||||
|
if (WRITE(outdes,&wavchunkhead,sizeof(struct wav_chunkhead_s))!=sizeof(struct wav_chunkhead_s)){
|
||||||
|
PRINTF_ERR("cannot write WAVE FMT header\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set FMT header */
|
||||||
|
wavfmthead.ftag[0]=0xff&WAV_HEAD_FTAG_PCM;
|
||||||
|
wavfmthead.ftag[1]=0xff&(WAV_HEAD_FTAG_PCM>>8);
|
||||||
|
wavfmthead.chnr[0]=0xff&chnr;
|
||||||
|
wavfmthead.chnr[1]=0xff&(chnr>>8);
|
||||||
|
wavfmthead.srate[0]=0xff&samprate;
|
||||||
|
wavfmthead.srate[1]=0xff&(samprate>>8);
|
||||||
|
wavfmthead.srate[2]=0xff&(samprate>>16);
|
||||||
|
wavfmthead.srate[3]=0xff&(samprate>>24);
|
||||||
|
drate=chnr*samprate*(bitnr/8); /* chnr!!! */
|
||||||
|
wavfmthead.drate[0]=0xff&drate;
|
||||||
|
wavfmthead.drate[1]=0xff&(drate>>8);
|
||||||
|
wavfmthead.drate[2]=0xff&(drate>>16);
|
||||||
|
wavfmthead.drate[3]=0xff&(drate>>24);
|
||||||
|
wavfmthead.balign[0]=0xff&((bitnr/8)*chnr); /* chnr!!! */
|
||||||
|
wavfmthead.balign[1]=0xff&(((bitnr/8)*chnr)>>8); /* chnr!!! */
|
||||||
|
wavfmthead.bitnr[0]=0xff&bitnr;
|
||||||
|
wavfmthead.bitnr[1]=0xff&(bitnr>>8);
|
||||||
|
|
||||||
|
/* write WAVE FMT header */
|
||||||
|
if (WRITE(outdes,&wavfmthead,sizeof(struct wav_fmthead_s))!=sizeof(struct wav_fmthead_s)){
|
||||||
|
PRINTF_ERR("cannot write WAVE FMT header\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* create WAVE DATA chunk header */
|
||||||
|
bcopy(WAV_CHUNKHEAD_DATASTR,wavchunkhead.typestr,4);
|
||||||
|
wavchunkhead.csize[0]=0xff&datasize;
|
||||||
|
wavchunkhead.csize[1]=0xff&(datasize>>8);
|
||||||
|
wavchunkhead.csize[2]=0xff&(datasize>>16);
|
||||||
|
wavchunkhead.csize[3]=0xff&(datasize>>24);
|
||||||
|
|
||||||
|
/* write chunk header */
|
||||||
|
if (WRITE(outdes,&wavchunkhead,sizeof(struct wav_chunkhead_s))!=sizeof(struct wav_chunkhead_s)){
|
||||||
|
PRINTF_ERR("cannot write WAVE DATA header\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
wav_read_head(int indes,
|
||||||
|
u_int *bcountp,
|
||||||
|
u_int *datasizep,u_int *chnrp,u_int *sampratep,u_int *bitnrp,
|
||||||
|
u_int *extrasizep,
|
||||||
|
char **errstrp)
|
||||||
|
{
|
||||||
|
struct wav_riffhead_s wavriffhead;
|
||||||
|
struct wav_chunkhead_s wavchunkhead;
|
||||||
|
struct wav_fmthead_s wavfmthead;
|
||||||
|
u_int i;
|
||||||
|
u_int bcount;
|
||||||
|
u_int remain;
|
||||||
|
u_int csize;
|
||||||
|
u_int chnr;
|
||||||
|
u_int samprate;
|
||||||
|
u_int bitnr;
|
||||||
|
|
||||||
|
bcount=0; /* no bytes read yet */
|
||||||
|
|
||||||
|
/* read WAVE RIFF header */
|
||||||
|
if (READ(indes,(char *)&wavriffhead,sizeof(struct wav_riffhead_s))!=sizeof(struct wav_riffhead_s)){
|
||||||
|
if (errstrp!=NULL){
|
||||||
|
*errstrp="read WAVE RIFF header";
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
bcount+=sizeof(struct wav_riffhead_s);
|
||||||
|
|
||||||
|
/* check riffstr */
|
||||||
|
for (i=0;i<4;i++){
|
||||||
|
if (WAV_RIFFHEAD_RIFFSTR[i]!=wavriffhead.riffstr[i]){
|
||||||
|
if (errstrp!=NULL){
|
||||||
|
*errstrp="no RIFF";
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* determine remaining file size */
|
||||||
|
remain=wavriffhead.fsize[0]
|
||||||
|
+(wavriffhead.fsize[1]<<8)
|
||||||
|
+(wavriffhead.fsize[2]<<16)
|
||||||
|
+(wavriffhead.fsize[3]<<24);
|
||||||
|
if (remain<sizeof(struct wav_riffhead_s)-sizeof(struct wav_chunkhead_s)){
|
||||||
|
if (errstrp!=NULL){
|
||||||
|
*errstrp="invalid file size";
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
remain-=sizeof(struct wav_riffhead_s)-sizeof(struct wav_chunkhead_s);
|
||||||
|
|
||||||
|
/* check wavestr */
|
||||||
|
for (i=0;i<4;i++){
|
||||||
|
if (WAV_RIFFHEAD_WAVESTR[i]!=wavriffhead.wavestr[i]){
|
||||||
|
if (errstrp!=NULL){
|
||||||
|
*errstrp="no WAVE";
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* search for fmt chunk */
|
||||||
|
for (;;){
|
||||||
|
/* read next chunk */
|
||||||
|
if (remain<sizeof(struct wav_chunkhead_s)){
|
||||||
|
if (errstrp!=NULL){
|
||||||
|
*errstrp="invalid file size";
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (READ(indes,(char *)&wavchunkhead,sizeof(struct wav_chunkhead_s))!=sizeof(struct wav_chunkhead_s)){
|
||||||
|
if (errstrp!=NULL){
|
||||||
|
*errstrp="read WAVE FMT header";
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
bcount+=sizeof(struct wav_chunkhead_s);
|
||||||
|
remain-=sizeof(struct wav_chunkhead_s);
|
||||||
|
|
||||||
|
/* get csize */
|
||||||
|
csize=wavchunkhead.csize[0]
|
||||||
|
+(wavchunkhead.csize[1]<<8)
|
||||||
|
+(wavchunkhead.csize[2]<<16)
|
||||||
|
+(wavchunkhead.csize[3]<<24);
|
||||||
|
if (remain<csize){
|
||||||
|
if (errstrp!=NULL){
|
||||||
|
*errstrp="invalid file size";
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i=0;i<4;i++){
|
||||||
|
if (WAV_CHUNKHEAD_FMTSTR[i]!=wavchunkhead.typestr[i]){
|
||||||
|
break; /* not fmt chunk */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i==4){
|
||||||
|
break; /* found fmt */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* skip rest of chunk */
|
||||||
|
if (LSEEK64(indes,(OFF64_T)csize,SEEK_CUR)<0){
|
||||||
|
if (errstrp!=NULL){
|
||||||
|
*errstrp="lseek WAVE FMT header";
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
bcount+=csize;
|
||||||
|
remain-=csize;
|
||||||
|
}
|
||||||
|
if (csize!=sizeof(struct wav_fmthead_s)){
|
||||||
|
if (errstrp!=NULL){
|
||||||
|
*errstrp="invalid FMT csize";
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* read rest of fmt chunk */
|
||||||
|
if (READ(indes,(char *)&wavfmthead,sizeof(struct wav_fmthead_s))!=sizeof(struct wav_fmthead_s)){
|
||||||
|
if (errstrp!=NULL){
|
||||||
|
*errstrp="read WAVE FMT header";
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
bcount+=sizeof(struct wav_fmthead_s);
|
||||||
|
remain-=sizeof(struct wav_fmthead_s);
|
||||||
|
|
||||||
|
/* check ftag */
|
||||||
|
/* XXX allow only PCM */
|
||||||
|
if ((wavfmthead.ftag[0]!=(0xff&WAV_HEAD_FTAG_PCM))
|
||||||
|
||(wavfmthead.ftag[1]!=(0xff&(WAV_HEAD_FTAG_PCM>>8)))){
|
||||||
|
if (errstrp!=NULL){
|
||||||
|
*errstrp="invalid ftag, must be PCM format";
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get chnr */
|
||||||
|
chnr=wavfmthead.chnr[0]
|
||||||
|
+(wavfmthead.chnr[1]<<8);
|
||||||
|
if (chnr==0){
|
||||||
|
if (errstrp!=NULL){
|
||||||
|
*errstrp="invalid chnr";
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set samprate */
|
||||||
|
samprate=wavfmthead.srate[0]
|
||||||
|
+(wavfmthead.srate[1]<<8)
|
||||||
|
+(wavfmthead.srate[2]<<16)
|
||||||
|
+(wavfmthead.srate[3]<<24);
|
||||||
|
|
||||||
|
/* XXX check drate: must be chnr*samprate*(bitnr/8) */
|
||||||
|
|
||||||
|
/* get bitnr */
|
||||||
|
bitnr=wavfmthead.bitnr[0]
|
||||||
|
+(wavfmthead.bitnr[1]<<8);
|
||||||
|
if (bitnr==0){
|
||||||
|
if (errstrp!=NULL){
|
||||||
|
*errstrp="invalid bitnr";
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* XXX check balign: must be (bitnr/8)*chnr */
|
||||||
|
|
||||||
|
/* search for data chunk */
|
||||||
|
for (;;){
|
||||||
|
/* read next chunk */
|
||||||
|
if (remain<sizeof(struct wav_chunkhead_s)){
|
||||||
|
if (errstrp!=NULL){
|
||||||
|
*errstrp="invalid file size";
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (READ(indes,(char *)&wavchunkhead,sizeof(struct wav_chunkhead_s))!=sizeof(struct wav_chunkhead_s)){
|
||||||
|
if (errstrp!=NULL){
|
||||||
|
*errstrp="read WAVE DATA header";
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
bcount+=sizeof(struct wav_chunkhead_s);
|
||||||
|
remain-=sizeof(struct wav_chunkhead_s);
|
||||||
|
|
||||||
|
/* get csize */
|
||||||
|
csize=wavchunkhead.csize[0]
|
||||||
|
+(wavchunkhead.csize[1]<<8)
|
||||||
|
+(wavchunkhead.csize[2]<<16)
|
||||||
|
+(wavchunkhead.csize[3]<<24);
|
||||||
|
if (remain<csize){
|
||||||
|
if (errstrp!=NULL){
|
||||||
|
*errstrp="invalid file size";
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i=0;i<4;i++){
|
||||||
|
if (WAV_CHUNKHEAD_DATASTR[i]!=wavchunkhead.typestr[i]){
|
||||||
|
break; /* not data chunk */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i==4){
|
||||||
|
break; /* found fmt */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* skip rest of chunk */
|
||||||
|
if (LSEEK64(indes,(OFF64_T)csize,SEEK_CUR)<0){
|
||||||
|
if (errstrp!=NULL){
|
||||||
|
*errstrp="lseek WAVE DATA header";
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
bcount+=csize;
|
||||||
|
remain-=csize;
|
||||||
|
}
|
||||||
|
if (csize%chnr!=0){
|
||||||
|
if (errstrp!=NULL){
|
||||||
|
*errstrp="invalid DATA csize";
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bcountp!=NULL){
|
||||||
|
*bcountp=bcount;
|
||||||
|
}
|
||||||
|
if (datasizep!=NULL){
|
||||||
|
*datasizep=csize;
|
||||||
|
}
|
||||||
|
if (chnrp!=NULL){
|
||||||
|
*chnrp=chnr;
|
||||||
|
}
|
||||||
|
if (sampratep!=NULL){
|
||||||
|
*sampratep=samprate;
|
||||||
|
}
|
||||||
|
if (bitnrp!=NULL){
|
||||||
|
*bitnrp=bitnr;
|
||||||
|
}
|
||||||
|
if (extrasizep!=NULL){
|
||||||
|
*extrasizep=remain-csize;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef WAV_AKAIHEAD_DISABLE
|
||||||
|
int
|
||||||
|
wav_find_akaihead(int indes,u_int *bcountp,u_int *csizep,u_int remain,u_int searchtype)
|
||||||
|
{
|
||||||
|
struct wav_chunkhead_s wavchunkhead;
|
||||||
|
u_int bcount;
|
||||||
|
u_int csize;
|
||||||
|
u_int type;
|
||||||
|
u_int i;
|
||||||
|
|
||||||
|
bcount=0; /* no bytes read yet */
|
||||||
|
csize=0; /* no chunk yet */
|
||||||
|
type=WAV_AKAIHEADTYPE_NONE; /* no AKAI header chunk found yet */
|
||||||
|
|
||||||
|
/* search for AKAI header chunk */
|
||||||
|
for (;;){
|
||||||
|
/* read next chunk */
|
||||||
|
if (remain<sizeof(struct wav_chunkhead_s)){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (READ(indes,(char *)&wavchunkhead,sizeof(struct wav_chunkhead_s))<0){
|
||||||
|
PRINTF_ERR("cannot read WAV chunk");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
bcount+=sizeof(struct wav_chunkhead_s);
|
||||||
|
remain-=sizeof(struct wav_chunkhead_s);
|
||||||
|
|
||||||
|
/* get csize */
|
||||||
|
csize=wavchunkhead.csize[0]
|
||||||
|
+(wavchunkhead.csize[1]<<8)
|
||||||
|
+(wavchunkhead.csize[2]<<16)
|
||||||
|
+(wavchunkhead.csize[3]<<24);
|
||||||
|
if (remain<csize){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((searchtype==WAV_AKAIHEADTYPE_NONE)||(searchtype==WAV_AKAIHEADTYPE_SAMPLE900)){
|
||||||
|
/* check if S900 sample header chunk */
|
||||||
|
for (i=0;i<4;i++){
|
||||||
|
if (WAV_CHUNKHEAD_AKAIS900SAMPLEHEADSTR[i]!=wavchunkhead.typestr[i]){
|
||||||
|
break; /* not data chunk */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i==4){
|
||||||
|
/* found */
|
||||||
|
type=WAV_AKAIHEADTYPE_SAMPLE900;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((searchtype==WAV_AKAIHEADTYPE_NONE)||(searchtype==WAV_AKAIHEADTYPE_SAMPLE1000)){
|
||||||
|
/* check if S1000 sample header chunk */
|
||||||
|
for (i=0;i<4;i++){
|
||||||
|
if (WAV_CHUNKHEAD_AKAIS1000SAMPLEHEADSTR[i]!=wavchunkhead.typestr[i]){
|
||||||
|
break; /* not data chunk */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i==4){
|
||||||
|
/* found */
|
||||||
|
type=WAV_AKAIHEADTYPE_SAMPLE1000;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((searchtype==WAV_AKAIHEADTYPE_NONE)||(searchtype==WAV_AKAIHEADTYPE_SAMPLE3000)){
|
||||||
|
/* check if S3000 sample header chunk */
|
||||||
|
for (i=0;i<4;i++){
|
||||||
|
if (WAV_CHUNKHEAD_AKAIS3000SAMPLEHEADSTR[i]!=wavchunkhead.typestr[i]){
|
||||||
|
break; /* not data chunk */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i==4){
|
||||||
|
/* found */
|
||||||
|
type=WAV_AKAIHEADTYPE_SAMPLE3000;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((searchtype==WAV_AKAIHEADTYPE_NONE)||(searchtype==WAV_AKAIHEADTYPE_DDTAKE)){
|
||||||
|
/* check if DD take header chunk */
|
||||||
|
for (i=0;i<4;i++){
|
||||||
|
if (WAV_CHUNKHEAD_AKAIDDTAKEHEADSTR[i]!=wavchunkhead.typestr[i]){
|
||||||
|
break; /* not data chunk */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i==4){
|
||||||
|
/* found */
|
||||||
|
type=WAV_AKAIHEADTYPE_DDTAKE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* skip rest of chunk */
|
||||||
|
if (LSEEK64(indes,(OFF64_T)csize,SEEK_CUR)<0){
|
||||||
|
PERROR("cannot lseek WAV chunk");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
bcount+=csize;
|
||||||
|
remain-=csize;
|
||||||
|
}
|
||||||
|
if (type==WAV_AKAIHEADTYPE_NONE){ /* no AKAI header chunk found? */
|
||||||
|
csize=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bcountp!=NULL){
|
||||||
|
*bcountp=bcount;
|
||||||
|
}
|
||||||
|
if (csizep!=NULL){
|
||||||
|
*csizep=csize;
|
||||||
|
}
|
||||||
|
return (int)type;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* EOF */
|
||||||
+99
@@ -0,0 +1,99 @@
|
|||||||
|
#ifndef __AKAIUTIL_WAV_H
|
||||||
|
#define __AKAIUTIL_WAV_H
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2010,2019 Klaus Michael Indlekofer. All rights reserved.
|
||||||
|
*
|
||||||
|
* m.indlekofer@gmx.de
|
||||||
|
*
|
||||||
|
* This program 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 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include "commoninclude.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* RIFF WAVE format header */
|
||||||
|
/* Note: WAV-file is little-endian!!! */
|
||||||
|
|
||||||
|
struct wav_riffhead_s{
|
||||||
|
/* begin RIFFWAVEChunk */
|
||||||
|
#define WAV_RIFFHEAD_RIFFSTR "RIFF"
|
||||||
|
char riffstr[4]; /* must be "RIFF" */
|
||||||
|
u_char fsize[4]; /* following file-size in Bytes */
|
||||||
|
#define WAV_RIFFHEAD_WAVESTR "WAVE"
|
||||||
|
char wavestr[4]; /* must be "WAVE" */
|
||||||
|
/* end RIFFWAVEChunk */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct wav_chunkhead_s{
|
||||||
|
char typestr[4]; /* chunk type */
|
||||||
|
u_char csize[4]; /* following chunk-size in Bytes */
|
||||||
|
};
|
||||||
|
#define WAV_CHUNKHEAD_FMTSTR "fmt "
|
||||||
|
#define WAV_CHUNKHEAD_DATASTR "data"
|
||||||
|
|
||||||
|
struct wav_fmthead_s{
|
||||||
|
/* continued FormatChunk */
|
||||||
|
#define WAV_HEAD_FTAG_PCM 0x0001 /* 1: PCM/umcompressed */
|
||||||
|
u_char ftag[2]; /* format tag */
|
||||||
|
u_char chnr[2]; /* number of channels */
|
||||||
|
u_char srate[4]; /* sample rate in samples/sec */
|
||||||
|
u_char drate[4]; /* total data rate in Bytes/sec */
|
||||||
|
u_char balign[2]; /* number of Bytes per sample * chnr */
|
||||||
|
u_char bitnr[2]; /* number of Bits per sample */
|
||||||
|
/* end FormatChunk */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define WAV_HEAD_SIZE (sizeof(struct wav_riffhead_s)+sizeof(struct wav_chunkhead_s)+sizeof(struct wav_fmthead_s)+sizeof(struct wav_chunkhead_s))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef WAV_AKAIHEAD_DISABLE
|
||||||
|
/* AKAI header chunks */
|
||||||
|
#define WAV_CHUNKHEAD_AKAIS900SAMPLEHEADSTR "S9H "
|
||||||
|
#define WAV_CHUNKHEAD_AKAIS1000SAMPLEHEADSTR "S1H "
|
||||||
|
#define WAV_CHUNKHEAD_AKAIS3000SAMPLEHEADSTR "S3H "
|
||||||
|
#define WAV_CHUNKHEAD_AKAIDDTAKEHEADSTR "TKH "
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Declarations */
|
||||||
|
|
||||||
|
extern int wav_write_head(int outdes,
|
||||||
|
u_int datasize,u_int chnr,u_int samprate,u_int bitnr,
|
||||||
|
u_int extrasize);
|
||||||
|
|
||||||
|
extern int wav_read_head(int indes,u_int *bcountp,
|
||||||
|
u_int *datasizep,u_int *chnrp,u_int *sampratep,u_int *bitnrp,
|
||||||
|
u_int *extrasizep,
|
||||||
|
char **errstrp);
|
||||||
|
|
||||||
|
#ifndef WAV_AKAIHEAD_DISABLE
|
||||||
|
#define WAV_AKAIHEADTYPE_NONE 0x00
|
||||||
|
#define WAV_AKAIHEADTYPE_SAMPLE900 0x09
|
||||||
|
#define WAV_AKAIHEADTYPE_SAMPLE1000 0x01
|
||||||
|
#define WAV_AKAIHEADTYPE_SAMPLE3000 0x03
|
||||||
|
#define WAV_AKAIHEADTYPE_DDTAKE 0xdd
|
||||||
|
int wav_find_akaihead(int indes,u_int *bcountp,u_int *csizep,u_int remain,u_int searchtype);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* !__AKAIUTIL_WAV_H */
|
||||||
+237
@@ -0,0 +1,237 @@
|
|||||||
|
#ifndef __COMMONINCLUDE_H
|
||||||
|
#define __COMMONINCLUDE_H
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2008,2010,2012,2019,2020,2021 Klaus Michael Indlekofer. All rights reserved.
|
||||||
|
*
|
||||||
|
* m.indlekofer@gmx.de
|
||||||
|
*
|
||||||
|
* This program 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 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef _VISUALCPP
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <Windows.h>
|
||||||
|
#include <io.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <limits.h>
|
||||||
|
/*#include <unistd.h>*/
|
||||||
|
/*#include <strings.h>*/
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
typedef unsigned char u_char;
|
||||||
|
typedef unsigned int u_int;
|
||||||
|
typedef unsigned long u_long;
|
||||||
|
typedef int ssize_t;
|
||||||
|
#ifndef SSIZE_MAX
|
||||||
|
#define SSIZE_MAX INT_MAX
|
||||||
|
#endif /* !SSIZE_MAX */
|
||||||
|
|
||||||
|
#define INT64 __int64
|
||||||
|
#define U_INT64 unsigned __int64
|
||||||
|
#define OFF_T __int64
|
||||||
|
#define OFF64_T __int64
|
||||||
|
|
||||||
|
#define OPEN _open
|
||||||
|
#define CLOSE _close
|
||||||
|
#define READ _read
|
||||||
|
#define WRITE _write
|
||||||
|
/* default lseek and off_t cannot handle offsets>=2GB! */
|
||||||
|
#define LSEEK _lseeki64
|
||||||
|
#define LSEEK64 _lseeki64
|
||||||
|
|
||||||
|
extern int strcasecmp(const char *s1,const char *s2);
|
||||||
|
extern int strncasecmp(const char *s1,const char *s2,size_t n);
|
||||||
|
|
||||||
|
/* getopt */
|
||||||
|
/*#include <unistd.h>*/
|
||||||
|
extern int getopt(int argc,char * const argv[],const char *optstring);
|
||||||
|
extern char *optarg;
|
||||||
|
extern int optind;
|
||||||
|
extern int opterr;
|
||||||
|
extern int optopt;
|
||||||
|
|
||||||
|
/* Note: returned value of _snprintf_s() can differ from returned value of snprintf() */
|
||||||
|
#define SNPRINTF(x,y,...) _snprintf_s((x),(y),_TRUNCATE,__VA_ARGS__)
|
||||||
|
|
||||||
|
/* XXX ignore returned value */
|
||||||
|
#define SYSTEM(x) {system(x);}
|
||||||
|
|
||||||
|
/* local (external) filesystem */
|
||||||
|
#include <direct.h>
|
||||||
|
#define LCHDIR(d) _chdir(d)
|
||||||
|
#define LDIR SYSTEM("dir")
|
||||||
|
#define LDELFILE(x,y,n) {_snprintf_s((x),(y),_TRUNCATE,"del /q /f \"%s\"",(n)); SYSTEM(x);}
|
||||||
|
|
||||||
|
/* play external WAV file */
|
||||||
|
#define PLAYWAV_PREPARE(x,y,n) SNPRINTF((x),(y),"%s",(n))
|
||||||
|
#define PLAYWAV_START(x) PlaySoundA((LPCSTR)(x),NULL,SND_ASYNC|SND_FILENAME|SND_NODEFAULT)
|
||||||
|
#define PLAYWAV_STOP PlaySoundA(NULL,NULL,0)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#else /* !_VISUALCPP */
|
||||||
|
/* e.g. UNIX-like systems or cygwin */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <strings.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#define INT64 __int64_t
|
||||||
|
#define U_INT64 __uint64_t
|
||||||
|
#define OFF_T off_t
|
||||||
|
#define OFF64_T int64_t
|
||||||
|
|
||||||
|
#ifndef NOT_MYLSEEK64
|
||||||
|
/* own 64bit version of lseek */
|
||||||
|
extern OFF64_T mylseek64(int filedes,OFF64_T offset,int whence);
|
||||||
|
#define LSEEK64 mylseek64
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __CYGWIN__
|
||||||
|
/* e.g. UNIX-like systems */
|
||||||
|
/* getopt */
|
||||||
|
#include <unistd.h>
|
||||||
|
extern int getopt(int argc,char * const argv[],const char *optstring);
|
||||||
|
extern char *optarg;
|
||||||
|
extern int optind;
|
||||||
|
extern int opterr;
|
||||||
|
extern int optopt;
|
||||||
|
#endif /* !__CYGWIN__*/
|
||||||
|
|
||||||
|
#define SNPRINTF(x,y,...) snprintf((x),(y),__VA_ARGS__)
|
||||||
|
|
||||||
|
/* XXX ignore returned value */
|
||||||
|
#define SYSTEM(x) {if (system(x)<0){;}}
|
||||||
|
|
||||||
|
/* local (external) filesystem */
|
||||||
|
#include <dirent.h>
|
||||||
|
#define LCHDIR(d) chdir(d)
|
||||||
|
#define LDIR SYSTEM("ls -la")
|
||||||
|
#define LDELFILE(x,y,n) {SNPRINTF((x),(y),"rm -f \"%s\"",(n)); SYSTEM(x);}
|
||||||
|
|
||||||
|
/* play external WAV file */
|
||||||
|
#ifndef PLAYWAV_CMD
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#define PLAYWAV_CMD "afplay"
|
||||||
|
#else /* !__APPLE__ */
|
||||||
|
/* use PulseAudio */
|
||||||
|
#define PLAYWAV_CMD "paplay"
|
||||||
|
#endif /* !__APPLE__ */
|
||||||
|
#endif /* !PLAYWAV_CMD */
|
||||||
|
#define PLAYWAV_PREPARE(x,y,n) snprintf((x),(y),PLAYWAV_CMD " \"%s\" > /dev/null 2>&1 &",(n))
|
||||||
|
#define PLAYWAV_START(x) SYSTEM((const char *)(x))
|
||||||
|
#define PLAYWAV_STOP SYSTEM("killall " PLAYWAV_CMD " > /dev/null 2>&1")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* !_VISUALCPP */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
/* O_BINARY important for Windows-based systems (esp. cygwin or VC++) */
|
||||||
|
#ifndef O_BINARY
|
||||||
|
#define O_BINARY 0
|
||||||
|
#endif /* !O_BINARY */
|
||||||
|
#ifndef OPEN
|
||||||
|
#define OPEN open
|
||||||
|
#endif
|
||||||
|
#ifndef CLOSE
|
||||||
|
#define CLOSE close
|
||||||
|
#endif
|
||||||
|
#ifndef READ
|
||||||
|
#define READ read
|
||||||
|
#endif
|
||||||
|
#ifndef WRITE
|
||||||
|
#define WRITE write
|
||||||
|
#endif
|
||||||
|
#ifndef LSEEK
|
||||||
|
#define LSEEK lseek
|
||||||
|
#endif
|
||||||
|
#ifndef LSEEK64
|
||||||
|
#define LSEEK64 lseek64
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern void bcopy(const void *src,void *dst,size_t len);
|
||||||
|
extern void bzero(void *b,size_t len);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef STRHEX_TO_UINT64
|
||||||
|
extern U_INT64 my_strhex_to_uint64(char *s);
|
||||||
|
#define STRHEX_TO_UINT64 my_strhex_to_uint64
|
||||||
|
#define USE_MY_STRHEX_TO_UINT64
|
||||||
|
#endif
|
||||||
|
#ifndef STRDEC_TO_UINT64
|
||||||
|
extern U_INT64 my_strdec_to_uint64(char *s);
|
||||||
|
#define STRDEC_TO_UINT64 my_strdec_to_uint64
|
||||||
|
#define USE_MY_STRDEC_TO_UINT64
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef UI_INCLUDE
|
||||||
|
/* external user interface */
|
||||||
|
#include UI_INCLUDE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* console I/O */
|
||||||
|
|
||||||
|
#ifndef FGETS
|
||||||
|
#define FGETS fgets
|
||||||
|
#endif
|
||||||
|
#ifndef PRINTF_OUT
|
||||||
|
#define PRINTF_OUT(...) fprintf(stdout,__VA_ARGS__)
|
||||||
|
#endif
|
||||||
|
#ifndef FLUSH_OUT
|
||||||
|
#define FLUSH_OUT fflush(stdout)
|
||||||
|
#endif
|
||||||
|
#ifndef PRINTF_ERR
|
||||||
|
#define PRINTF_ERR(...) fprintf(stderr,__VA_ARGS__)
|
||||||
|
#endif
|
||||||
|
#ifndef PERROR
|
||||||
|
#include <errno.h>
|
||||||
|
#define PERROR(x) PRINTF_ERR("%s: %s\n",x,strerror(errno))
|
||||||
|
#endif
|
||||||
|
#ifndef FLUSH_ALL
|
||||||
|
#define FLUSH_ALL fflush(NULL)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* !__COMMONINCLUDE_H */
|
||||||
+454
@@ -0,0 +1,454 @@
|
|||||||
|
/*
|
||||||
|
* unless noted otherwise: Copyright (C) 2003-2010,2019,2020,2021 Klaus Michael Indlekofer. All rights reserved.
|
||||||
|
*
|
||||||
|
* m.indlekofer@gmx.de
|
||||||
|
*
|
||||||
|
* This program 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 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include "commoninclude.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef _VISUALCPP
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* bcopy, bzero */
|
||||||
|
/* (c) 2003, 2004 by K. M. Indlekofer */
|
||||||
|
void
|
||||||
|
bcopy(const void *src,void *dst,size_t len)
|
||||||
|
{
|
||||||
|
char *cp1,*cp2;
|
||||||
|
|
||||||
|
cp1=(char *)src;
|
||||||
|
cp2=(char *)dst;
|
||||||
|
/* XXX no check for NULL pointer */
|
||||||
|
while (len-->0){
|
||||||
|
*cp2=*cp1;
|
||||||
|
cp1++;
|
||||||
|
cp2++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
bzero(void *b,size_t len)
|
||||||
|
{
|
||||||
|
char *cp;
|
||||||
|
|
||||||
|
cp=(char *)b;
|
||||||
|
/* XXX no check for NULL pointer */
|
||||||
|
while (len-->0){
|
||||||
|
*cp=0;
|
||||||
|
cp++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* strcasecmp */
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1987, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by the University of
|
||||||
|
* California, Berkeley and its contributors.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This array is designed for mapping upper and lower case letter
|
||||||
|
* together for a case independent comparison. The mappings are
|
||||||
|
* based upon ascii character sequences.
|
||||||
|
*/
|
||||||
|
static const u_char charmap[] = {
|
||||||
|
0000, 0001, 0002, 0003, 0004, 0005, 0006, 0007,
|
||||||
|
0010, 0011, 0012, 0013, 0014, 0015, 0016, 0017,
|
||||||
|
0020, 0021, 0022, 0023, 0024, 0025, 0026, 0027,
|
||||||
|
0030, 0031, 0032, 0033, 0034, 0035, 0036, 0037,
|
||||||
|
0040, 0041, 0042, 0043, 0044, 0045, 0046, 0047,
|
||||||
|
0050, 0051, 0052, 0053, 0054, 0055, 0056, 0057,
|
||||||
|
0060, 0061, 0062, 0063, 0064, 0065, 0066, 0067,
|
||||||
|
0070, 0071, 0072, 0073, 0074, 0075, 0076, 0077,
|
||||||
|
0100, 0141, 0142, 0143, 0144, 0145, 0146, 0147,
|
||||||
|
0150, 0151, 0152, 0153, 0154, 0155, 0156, 0157,
|
||||||
|
0160, 0161, 0162, 0163, 0164, 0165, 0166, 0167,
|
||||||
|
0170, 0171, 0172, 0133, 0134, 0135, 0136, 0137,
|
||||||
|
0140, 0141, 0142, 0143, 0144, 0145, 0146, 0147,
|
||||||
|
0150, 0151, 0152, 0153, 0154, 0155, 0156, 0157,
|
||||||
|
0160, 0161, 0162, 0163, 0164, 0165, 0166, 0167,
|
||||||
|
0170, 0171, 0172, 0173, 0174, 0175, 0176, 0177,
|
||||||
|
0200, 0201, 0202, 0203, 0204, 0205, 0206, 0207,
|
||||||
|
0210, 0211, 0212, 0213, 0214, 0215, 0216, 0217,
|
||||||
|
0220, 0221, 0222, 0223, 0224, 0225, 0226, 0227,
|
||||||
|
0230, 0231, 0232, 0233, 0234, 0235, 0236, 0237,
|
||||||
|
0240, 0241, 0242, 0243, 0244, 0245, 0246, 0247,
|
||||||
|
0250, 0251, 0252, 0253, 0254, 0255, 0256, 0257,
|
||||||
|
0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267,
|
||||||
|
0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277,
|
||||||
|
0300, 0301, 0302, 0303, 0304, 0305, 0306, 0307,
|
||||||
|
0310, 0311, 0312, 0313, 0314, 0315, 0316, 0317,
|
||||||
|
0320, 0321, 0322, 0323, 0324, 0325, 0326, 0327,
|
||||||
|
0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337,
|
||||||
|
0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347,
|
||||||
|
0350, 0351, 0352, 0353, 0354, 0355, 0356, 0357,
|
||||||
|
0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367,
|
||||||
|
0370, 0371, 0372, 0373, 0374, 0375, 0376, 0377
|
||||||
|
};
|
||||||
|
|
||||||
|
int
|
||||||
|
strcasecmp(const char *s1, const char *s2) {
|
||||||
|
const u_char *cm = charmap,
|
||||||
|
*us1 = (const u_char *)s1,
|
||||||
|
*us2 = (const u_char *)s2;
|
||||||
|
|
||||||
|
while (cm[*us1] == cm[*us2++])
|
||||||
|
if (*us1++ == '\0')
|
||||||
|
return (0);
|
||||||
|
return (cm[*us1] - cm[*--us2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
strncasecmp(const char *s1, const char *s2, size_t n) {
|
||||||
|
if (n != 0) {
|
||||||
|
const u_char *cm = charmap,
|
||||||
|
*us1 = (const u_char *)s1,
|
||||||
|
*us2 = (const u_char *)s2;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (cm[*us1] != cm[*us2++])
|
||||||
|
return (cm[*us1] - cm[*--us2]);
|
||||||
|
if (*us1++ == '\0')
|
||||||
|
break;
|
||||||
|
} while (--n != 0);
|
||||||
|
}
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* getopt */
|
||||||
|
/*
|
||||||
|
* getopt.c --
|
||||||
|
*
|
||||||
|
* Standard UNIX getopt function. Code is from BSD.
|
||||||
|
*
|
||||||
|
* Copyright (c) 1987-2002 The Regents of the University of California.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* A. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* B. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
* C. Neither the names of the copyright holders nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
|
||||||
|
* IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
/* modified by K.M.Indlekofer */
|
||||||
|
|
||||||
|
/* #if !defined(lint)
|
||||||
|
* static char sccsid[] = "@(#)getopt.c 8.2 (Berkeley) 4/2/94";
|
||||||
|
* #endif
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/* declarations to provide consistent linkage */
|
||||||
|
extern char *optarg;
|
||||||
|
extern int optind;
|
||||||
|
extern int opterr;
|
||||||
|
|
||||||
|
int opterr = 1, /* if error message should be printed */
|
||||||
|
optind = 1, /* index into parent argv vector */
|
||||||
|
optopt, /* character checked for validity */
|
||||||
|
optreset; /* reset getopt */
|
||||||
|
char *optarg; /* argument associated with option */
|
||||||
|
|
||||||
|
#define BADCH (int)'?'
|
||||||
|
#define BADARG (int)':'
|
||||||
|
#define EMSG ""
|
||||||
|
|
||||||
|
/*
|
||||||
|
* getopt --
|
||||||
|
* Parse argc/argv argument vector.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
getopt(nargc, nargv, ostr)
|
||||||
|
int nargc;
|
||||||
|
char * const *nargv;
|
||||||
|
const char *ostr;
|
||||||
|
{
|
||||||
|
static char *place = EMSG; /* option letter processing */
|
||||||
|
char *oli; /* option letter list index */
|
||||||
|
|
||||||
|
if (optreset || !*place) { /* update scanning pointer */
|
||||||
|
optreset = 0;
|
||||||
|
if (optind >= nargc || *(place = nargv[optind]) != '-') {
|
||||||
|
place = EMSG;
|
||||||
|
return (EOF);
|
||||||
|
}
|
||||||
|
if (place[1] && *++place == '-') { /* found "--" */
|
||||||
|
++optind;
|
||||||
|
place = EMSG;
|
||||||
|
return (EOF);
|
||||||
|
}
|
||||||
|
} /* option letter okay? */
|
||||||
|
if ((optopt = (int)*place++) == (int)':' ||
|
||||||
|
!(oli = strchr(ostr, optopt))) {
|
||||||
|
/*
|
||||||
|
* if the user didn't specify '-' as an option,
|
||||||
|
* assume it means EOF.
|
||||||
|
*/
|
||||||
|
if (optopt == (int)'-')
|
||||||
|
return (EOF);
|
||||||
|
if (!*place)
|
||||||
|
++optind;
|
||||||
|
#ifdef GETOPT_PRINTF_ERR
|
||||||
|
if (opterr && *ostr != ':')
|
||||||
|
(void)GETOPT_PRINTF_ERR(
|
||||||
|
"%s: illegal option -- %c\n", __FILE__, optopt);
|
||||||
|
#endif
|
||||||
|
return (BADCH);
|
||||||
|
}
|
||||||
|
if (*++oli != ':') { /* don't need argument */
|
||||||
|
optarg = NULL;
|
||||||
|
if (!*place)
|
||||||
|
++optind;
|
||||||
|
}
|
||||||
|
else { /* need an argument */
|
||||||
|
if (*place) /* no white space */
|
||||||
|
optarg = place;
|
||||||
|
else if (nargc <= ++optind) { /* no arg */
|
||||||
|
place = EMSG;
|
||||||
|
if (*ostr == ':')
|
||||||
|
return (BADARG);
|
||||||
|
#ifdef GETOPT_PRINTF_ERR
|
||||||
|
if (opterr)
|
||||||
|
(void)GETOPT_PRINTF_ERR(
|
||||||
|
"%s: option requires an argument -- %c\n",
|
||||||
|
__FILE__, optopt);
|
||||||
|
#endif
|
||||||
|
return (BADCH);
|
||||||
|
}
|
||||||
|
else /* white space */
|
||||||
|
optarg = nargv[optind];
|
||||||
|
place = EMSG;
|
||||||
|
++optind;
|
||||||
|
}
|
||||||
|
return (optopt); /* dump back option letter */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#else /* !_VISUALCPP */
|
||||||
|
/* e.g. UNIX-like systems or cygwin */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef NOT_MYLSEEK64
|
||||||
|
/* own 64bit version of lseek */
|
||||||
|
OFF64_T
|
||||||
|
mylseek64(int filedes,OFF64_T offset,int whence)
|
||||||
|
{
|
||||||
|
OFF64_T remain;
|
||||||
|
OFF64_T chunk;
|
||||||
|
OFF64_T ret;
|
||||||
|
OFF64_T c;
|
||||||
|
int whence2;
|
||||||
|
|
||||||
|
ret=0;
|
||||||
|
remain=offset;
|
||||||
|
for (c=0;;c++){
|
||||||
|
chunk=remain;
|
||||||
|
if (chunk>0x40000000){ /* XXX */
|
||||||
|
chunk=0x40000000;
|
||||||
|
}else if (chunk<-0x40000000){
|
||||||
|
chunk=-0x40000000;
|
||||||
|
}
|
||||||
|
if ((whence==SEEK_SET)&&(c>0)){ /* SEEK_SET and not first chunk? */
|
||||||
|
whence2=SEEK_CUR;
|
||||||
|
}else{
|
||||||
|
whence2=whence;
|
||||||
|
}
|
||||||
|
#if defined(DEBUGIO)&&defined(MYLSEEK64_PRINTF)
|
||||||
|
MYLSEEK64_PRINTF("c:%08x%08x chunk:%08x\n",(u_int)(c>>32),(u_int)c,(u_int)chunk);
|
||||||
|
#endif
|
||||||
|
if (LSEEK(filedes,(OFF_T)chunk,whence2)<0){
|
||||||
|
ret=-1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (remain==0){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
remain-=chunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret<0){
|
||||||
|
return ret;
|
||||||
|
}else{
|
||||||
|
return offset-remain;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* !NOT_MYLSEEK64 */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* !_VISUALCPP */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef USE_MY_STRHEX_TO_UINT64
|
||||||
|
U_INT64
|
||||||
|
my_strhex_to_uint64(char *s)
|
||||||
|
{
|
||||||
|
u_int l;
|
||||||
|
u_int u1,u2;
|
||||||
|
U_INT64 u;
|
||||||
|
static char s2[8+1]; /* XXX max. 8 upper digits */
|
||||||
|
|
||||||
|
if (s==NULL){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
l=(u_int)strlen(s);
|
||||||
|
if (l==0){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* XXX can handle max. 16 digits */
|
||||||
|
if (l>8){
|
||||||
|
#if 1
|
||||||
|
sscanf(s+l-8,"%x",&u1); /* lower 8 digits */
|
||||||
|
#else
|
||||||
|
u1=strtol(s+l-8,NULL,16); /* lower 8 digits */
|
||||||
|
#endif
|
||||||
|
strncpy(s2,
|
||||||
|
s+((l>16)?(l-16):0),
|
||||||
|
(((l-8)<=8)?(l-8):8)); /* XXX max. 8 upper digits */
|
||||||
|
s2[8]='\0';
|
||||||
|
#if 1
|
||||||
|
sscanf(s2,"%x",&u2); /* upper digits */
|
||||||
|
#else
|
||||||
|
u2=strtol(s2,NULL,16); /* upper digits */
|
||||||
|
#endif
|
||||||
|
u=(((U_INT64)u2)<<32)|((U_INT64)u1);
|
||||||
|
}else{
|
||||||
|
#if 1
|
||||||
|
sscanf(s,"%x",&u1);
|
||||||
|
u=(U_INT64)u1;
|
||||||
|
#else
|
||||||
|
u=(U_INT64)strtol(s,NULL,16);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return u;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_MY_STRDEC_TO_UINT64
|
||||||
|
U_INT64
|
||||||
|
my_strdec_to_uint64(char *s)
|
||||||
|
{
|
||||||
|
u_int l;
|
||||||
|
u_int u1,u2;
|
||||||
|
U_INT64 u;
|
||||||
|
static char s2[9+1]; /* XXX max. 9 upper digits */
|
||||||
|
|
||||||
|
if (s==NULL){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
l=(u_int)strlen(s);
|
||||||
|
if (l==0){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* XXX can handle max. 18 digits */
|
||||||
|
if (l>9){
|
||||||
|
#if 1
|
||||||
|
sscanf(s+l-9,"%u",&u1); /* lower 9 digits */
|
||||||
|
#else
|
||||||
|
u1=strtol(s+l-9,NULL,10); /* lower 9 digits */
|
||||||
|
#endif
|
||||||
|
strncpy(s2,
|
||||||
|
s+((l>18)?(l-18):0),
|
||||||
|
(((l-9)<=9)?(l-9):9)); /* XXX max. 9 upper digits */
|
||||||
|
s2[9]='\0';
|
||||||
|
#if 1
|
||||||
|
sscanf(s2,"%u",&u2); /* upper digits */
|
||||||
|
#else
|
||||||
|
u2=strtol(s2,NULL,10); /* upper digits */
|
||||||
|
#endif
|
||||||
|
u=((U_INT64)u2)*((U_INT64)1000000000)+((U_INT64)u1);
|
||||||
|
}else{
|
||||||
|
#if 1
|
||||||
|
sscanf(s,"%u",&u1);
|
||||||
|
u=(U_INT64)u1;
|
||||||
|
#else
|
||||||
|
u=(U_INT64)strtol(s,NULL,10);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return u;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* EOF */
|
||||||
+299
@@ -0,0 +1,299 @@
|
|||||||
|
// fdrawcmd.sys 1.0.1.11
|
||||||
|
//
|
||||||
|
// Low-level floppy filter, by Simon Owen
|
||||||
|
//
|
||||||
|
// http://simonowen.com/fdrawcmd/
|
||||||
|
|
||||||
|
#ifndef FDRAWCMD_H
|
||||||
|
#define FDRAWCMD_H
|
||||||
|
|
||||||
|
#ifndef CTL_CODE
|
||||||
|
#include <winioctl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define FDRAWCMD_VERSION 0x0100010b // Compile-time version, for structures and definitions below
|
||||||
|
// Must be checked with run-time driver for compatibility
|
||||||
|
|
||||||
|
#define FD_CTL_CODE(i,m) CTL_CODE(FILE_DEVICE_UNKNOWN, i, m, FILE_READ_DATA|FILE_WRITE_DATA)
|
||||||
|
|
||||||
|
// If you're not using C/C++, use the IOCTL values below
|
||||||
|
#define IOCTL_FDRAWCMD_GET_VERSION FD_CTL_CODE(0x888, METHOD_BUFFERED) // 0x0022e220
|
||||||
|
|
||||||
|
#define IOCTL_FDCMD_READ_TRACK FD_CTL_CODE(0x802, METHOD_OUT_DIRECT) // 0x0022e00a
|
||||||
|
#define IOCTL_FDCMD_SPECIFY FD_CTL_CODE(0x803, METHOD_BUFFERED) // 0x0022e00c
|
||||||
|
#define IOCTL_FDCMD_SENSE_DRIVE_STATUS FD_CTL_CODE(0x804, METHOD_BUFFERED) // 0x0022e010
|
||||||
|
#define IOCTL_FDCMD_WRITE_DATA FD_CTL_CODE(0x805, METHOD_IN_DIRECT) // 0x0022e015
|
||||||
|
#define IOCTL_FDCMD_READ_DATA FD_CTL_CODE(0x806, METHOD_OUT_DIRECT) // 0x0022e01a
|
||||||
|
#define IOCTL_FDCMD_RECALIBRATE FD_CTL_CODE(0x807, METHOD_BUFFERED) // 0x0022e01c
|
||||||
|
#define IOCTL_FDCMD_SENSE_INT_STATUS FD_CTL_CODE(0x808, METHOD_BUFFERED) // 0x0022e020 // added in 1.0.0.22
|
||||||
|
#define IOCTL_FDCMD_WRITE_DELETED_DATA FD_CTL_CODE(0x809, METHOD_IN_DIRECT) // 0x0022e025
|
||||||
|
#define IOCTL_FDCMD_READ_ID FD_CTL_CODE(0x80a, METHOD_BUFFERED) // 0x0022e028
|
||||||
|
#define IOCTL_FDCMD_READ_DELETED_DATA FD_CTL_CODE(0x80c, METHOD_OUT_DIRECT) // 0x0022e032
|
||||||
|
#define IOCTL_FDCMD_FORMAT_TRACK FD_CTL_CODE(0x80d, METHOD_BUFFERED) // 0x0022e034
|
||||||
|
#define IOCTL_FDCMD_DUMPREG FD_CTL_CODE(0x80e, METHOD_BUFFERED) // 0x0022e038
|
||||||
|
#define IOCTL_FDCMD_SEEK FD_CTL_CODE(0x80f, METHOD_BUFFERED) // 0x0022e03c
|
||||||
|
#define IOCTL_FDCMD_VERSION FD_CTL_CODE(0x810, METHOD_BUFFERED) // 0x0022e040
|
||||||
|
#define IOCTL_FDCMD_SCAN_EQUAL FD_CTL_CODE(0x811, METHOD_IN_DIRECT) // 0x0022e045 (not implemented yet)
|
||||||
|
#define IOCTL_FDCMD_PERPENDICULAR_MODE FD_CTL_CODE(0x812, METHOD_BUFFERED) // 0x0022e048
|
||||||
|
#define IOCTL_FDCMD_CONFIGURE FD_CTL_CODE(0x813, METHOD_BUFFERED) // 0x0022e04c
|
||||||
|
#define IOCTL_FDCMD_LOCK FD_CTL_CODE(0x814, METHOD_BUFFERED) // 0x0022e050
|
||||||
|
#define IOCTL_FDCMD_VERIFY FD_CTL_CODE(0x816, METHOD_BUFFERED) // 0x0022e058
|
||||||
|
#define IOCTL_FDCMD_POWERDOWN_MODE FD_CTL_CODE(0x817, METHOD_BUFFERED) // 0x0022e05c (not implemented yet)
|
||||||
|
#define IOCTL_FDCMD_PART_ID FD_CTL_CODE(0x818, METHOD_BUFFERED) // 0x0022e060
|
||||||
|
#define IOCTL_FDCMD_SCAN_LOW_OR_EQUAL FD_CTL_CODE(0x819, METHOD_IN_DIRECT) // 0x0022e065 (not implemented yet)
|
||||||
|
#define IOCTL_FDCMD_SCAN_HIGH_OR_EQUAL FD_CTL_CODE(0x81d, METHOD_IN_DIRECT) // 0x0022e075 (not implemented yet)
|
||||||
|
#define IOCTL_FDCMD_SAVE FD_CTL_CODE(0x82e, METHOD_BUFFERED) // 0x0022e0b8 (not implemented yet)
|
||||||
|
#define IOCTL_FDCMD_OPTION FD_CTL_CODE(0x833, METHOD_BUFFERED) // 0x0022e0cc (not implemented yet)
|
||||||
|
#define IOCTL_FDCMD_RESTORE FD_CTL_CODE(0x84e, METHOD_BUFFERED) // 0x0022e138 (not implemented yet)
|
||||||
|
#define IOCTL_FDCMD_DRIVE_SPEC_CMD FD_CTL_CODE(0x88e, METHOD_BUFFERED) // 0x0022e238 (not implemented yet)
|
||||||
|
#define IOCTL_FDCMD_RELATIVE_SEEK FD_CTL_CODE(0x88f, METHOD_BUFFERED) // 0x0022e23c
|
||||||
|
#define IOCTL_FDCMD_FORMAT_AND_WRITE FD_CTL_CODE(0x8ef, METHOD_BUFFERED) // 0x0022e3bc // added in 1.0.1.10
|
||||||
|
|
||||||
|
#define IOCTL_FD_SCAN_TRACK FD_CTL_CODE(0x900, METHOD_BUFFERED) // 0x0022e400
|
||||||
|
#define IOCTL_FD_GET_RESULT FD_CTL_CODE(0x901, METHOD_BUFFERED) // 0x0022e404
|
||||||
|
#define IOCTL_FD_RESET FD_CTL_CODE(0x902, METHOD_BUFFERED) // 0x0022e408
|
||||||
|
#define IOCTL_FD_SET_MOTOR_TIMEOUT FD_CTL_CODE(0x903, METHOD_BUFFERED) // 0x0022e40c
|
||||||
|
#define IOCTL_FD_SET_DATA_RATE FD_CTL_CODE(0x904, METHOD_BUFFERED) // 0x0022e410
|
||||||
|
#define IOCTL_FD_GET_FDC_INFO FD_CTL_CODE(0x905, METHOD_BUFFERED) // 0x0022e414
|
||||||
|
#define IOCTL_FD_GET_REMAIN_COUNT FD_CTL_CODE(0x906, METHOD_BUFFERED) // 0x0022e418 // added in 1.0.0.22
|
||||||
|
#define IOCTL_FD_SET_DISK_CHECK FD_CTL_CODE(0x908, METHOD_BUFFERED) // 0x0022e420
|
||||||
|
#define IOCTL_FD_SET_SHORT_WRITE FD_CTL_CODE(0x909, METHOD_BUFFERED) // 0x0022e424 // added in 1.0.0.22
|
||||||
|
#define IOCTL_FD_SET_SECTOR_OFFSET FD_CTL_CODE(0x90a, METHOD_BUFFERED) // 0x0022e428 // added in 1.0.0.22
|
||||||
|
#define IOCTL_FD_SET_HEAD_SETTLE_TIME FD_CTL_CODE(0x90b, METHOD_BUFFERED) // 0x0022e42c // added in 1.0.0.22
|
||||||
|
#define IOCTL_FD_LOCK_FDC FD_CTL_CODE(0x910, METHOD_BUFFERED) // 0x0022e440 // obsolete from 1.0.1.0
|
||||||
|
#define IOCTL_FD_UNLOCK_FDC FD_CTL_CODE(0x911, METHOD_BUFFERED) // 0x0022e444 // obsolete from 1.0.1.0
|
||||||
|
#define IOCTL_FD_MOTOR_ON FD_CTL_CODE(0x912, METHOD_BUFFERED) // 0x0022e448
|
||||||
|
#define IOCTL_FD_MOTOR_OFF FD_CTL_CODE(0x913, METHOD_BUFFERED) // 0x0022e44c
|
||||||
|
#define IOCTL_FD_WAIT_INDEX FD_CTL_CODE(0x914, METHOD_BUFFERED) // 0x0022e450 // added in 1.0.0.22
|
||||||
|
#define IOCTL_FD_TIMED_SCAN_TRACK FD_CTL_CODE(0x915, METHOD_BUFFERED) // 0x0022e454 // added in 1.0.0.22
|
||||||
|
#define IOCTL_FD_RAW_READ_TRACK FD_CTL_CODE(0x916, METHOD_OUT_DIRECT) // 0x0022e45a // added in 1.0.1.4
|
||||||
|
#define IOCTL_FD_CHECK_DISK FD_CTL_CODE(0x917, METHOD_BUFFERED) // 0x0022e45c // added in 1.0.1.10
|
||||||
|
#define IOCTL_FD_GET_TRACK_TIME FD_CTL_CODE(0x918, METHOD_BUFFERED) // 0x0022e460 // added in 1.0.1.10
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Command flags: multi-track, MFM, sector skip, relative seek direction, verify enable count
|
||||||
|
#define FD_OPTION_MT 0x80
|
||||||
|
#define FD_OPTION_MFM 0x40
|
||||||
|
#define FD_OPTION_SK 0x20
|
||||||
|
#define FD_OPTION_DIR 0x40
|
||||||
|
#define FD_OPTION_EC 0x01
|
||||||
|
#define FD_OPTION_FM 0x00
|
||||||
|
#define FD_ENCODING_MASK FD_OPTION_MFM
|
||||||
|
|
||||||
|
// Controller data rates, for use with IOCTL_FD_SET_DATA_RATE
|
||||||
|
#define FD_RATE_MASK 3
|
||||||
|
#define FD_RATE_500K 0
|
||||||
|
#define FD_RATE_300K 1
|
||||||
|
#define FD_RATE_250K 2
|
||||||
|
#define FD_RATE_1M 3
|
||||||
|
|
||||||
|
// FD_FDC_INFO controller types
|
||||||
|
#define FDC_TYPE_UNKNOWN 0
|
||||||
|
#define FDC_TYPE_UNKNOWN2 1
|
||||||
|
#define FDC_TYPE_NORMAL 2
|
||||||
|
#define FDC_TYPE_ENHANCED 3
|
||||||
|
#define FDC_TYPE_82077 4
|
||||||
|
#define FDC_TYPE_82077AA 5
|
||||||
|
#define FDC_TYPE_82078_44 6
|
||||||
|
#define FDC_TYPE_82078_64 7
|
||||||
|
#define FDC_TYPE_NATIONAL 8
|
||||||
|
|
||||||
|
// Bits representing supported data rates, for the FD_FDC_INFO structure below
|
||||||
|
#define FDC_SPEED_250K 0x01
|
||||||
|
#define FDC_SPEED_300K 0x02
|
||||||
|
#define FDC_SPEED_500K 0x04
|
||||||
|
#define FDC_SPEED_1M 0x08
|
||||||
|
#define FDC_SPEED_2M 0x10
|
||||||
|
|
||||||
|
|
||||||
|
#pragma pack(push,1)
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable:4200) // allow zero-sized arrays
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct tagFD_ID_HEADER
|
||||||
|
{
|
||||||
|
BYTE cyl, head, sector, size;
|
||||||
|
}
|
||||||
|
FD_ID_HEADER, *PFD_ID_HEADER;
|
||||||
|
|
||||||
|
typedef struct tagFD_SEEK_PARAMS
|
||||||
|
{
|
||||||
|
BYTE cyl;
|
||||||
|
BYTE head;
|
||||||
|
}
|
||||||
|
FD_SEEK_PARAMS, *PFD_SEEK_PARAMS;
|
||||||
|
|
||||||
|
typedef struct tagFD_RELATIVE_SEEK_PARAMS
|
||||||
|
{
|
||||||
|
BYTE flags; // DIR
|
||||||
|
BYTE head;
|
||||||
|
BYTE offset;
|
||||||
|
}
|
||||||
|
FD_RELATIVE_SEEK_PARAMS, *PFD_RELATIVE_SEEK_PARAMS;
|
||||||
|
|
||||||
|
typedef struct tagFD_READ_WRITE_PARAMS
|
||||||
|
{
|
||||||
|
BYTE flags; // MT MFM SK
|
||||||
|
BYTE phead;
|
||||||
|
BYTE cyl, head, sector, size;
|
||||||
|
BYTE eot, gap, datalen;
|
||||||
|
}
|
||||||
|
FD_READ_WRITE_PARAMS, *PFD_READ_WRITE_PARAMS;
|
||||||
|
|
||||||
|
typedef struct tagFD_CMD_RESULT
|
||||||
|
{
|
||||||
|
BYTE st0, st1, st2;
|
||||||
|
BYTE cyl, head, sector, size;
|
||||||
|
}
|
||||||
|
FD_CMD_RESULT, *PFD_CMD_RESULT;
|
||||||
|
|
||||||
|
typedef struct tagFD_FORMAT_PARAMS
|
||||||
|
{
|
||||||
|
BYTE flags; // MFM
|
||||||
|
BYTE phead;
|
||||||
|
BYTE size, sectors, gap, fill;
|
||||||
|
|
||||||
|
FD_ID_HEADER Header[];
|
||||||
|
}
|
||||||
|
FD_FORMAT_PARAMS, *PFD_FORMAT_PARAMS;
|
||||||
|
|
||||||
|
typedef struct tagFD_READ_ID_PARAMS
|
||||||
|
{
|
||||||
|
BYTE flags; // MFM
|
||||||
|
BYTE head;
|
||||||
|
}
|
||||||
|
FD_READ_ID_PARAMS, *PFD_READ_ID_PARAMS;
|
||||||
|
|
||||||
|
typedef struct tagFD_CONFIGURE_PARAMS
|
||||||
|
{
|
||||||
|
BYTE eis_efifo_poll_fifothr; // b6 = enable implied seek, b5 = enable fifo, b4 = poll disable, b3-b0 = fifo threshold
|
||||||
|
BYTE pretrk; // precompensation start track
|
||||||
|
}
|
||||||
|
FD_CONFIGURE_PARAMS, *PFD_CONFIGURE_PARAMS;
|
||||||
|
|
||||||
|
typedef struct tagFD_SPECIFY_PARAMS
|
||||||
|
{
|
||||||
|
BYTE srt_hut; // b7-b4 = step rate, b3-b0 = head unload time
|
||||||
|
BYTE hlt_nd; // b7-b1 = head load time, b0 = non-DMA flag (unsupported)
|
||||||
|
}
|
||||||
|
FD_SPECIFY_PARAMS, *PFD_SPECIFY_PARAMS;
|
||||||
|
|
||||||
|
typedef struct tagFD_SENSE_PARAMS
|
||||||
|
{
|
||||||
|
BYTE head;
|
||||||
|
}
|
||||||
|
FD_SENSE_PARAMS, *PFD_SENSE_PARAMS;
|
||||||
|
|
||||||
|
typedef struct tagFD_DRIVE_STATUS
|
||||||
|
{
|
||||||
|
BYTE st3;
|
||||||
|
}
|
||||||
|
FD_DRIVE_STATUS, *PFD_DRIVE_STATUS;
|
||||||
|
|
||||||
|
typedef struct tagFD_INTERRUPT_STATUS
|
||||||
|
{
|
||||||
|
BYTE st0; // status register 0
|
||||||
|
BYTE pcn; // present cylinder number
|
||||||
|
}
|
||||||
|
FD_INTERRUPT_STATUS, *PFD_INTERRUPT_STATUS;
|
||||||
|
|
||||||
|
typedef struct tagFD_PERPENDICULAR_PARAMS
|
||||||
|
{
|
||||||
|
BYTE ow_ds_gap_wgate; // b7 = OW, b6 = 0, b5-b2 = drive select, b1 = gap2, b0 = write gate pre-erase loads
|
||||||
|
}
|
||||||
|
FD_PERPENDICULAR_PARAMS, *PFD_PERPENDICULAR_PARAMS;
|
||||||
|
|
||||||
|
typedef struct tagFD_LOCK_PARAMS
|
||||||
|
{
|
||||||
|
BYTE lock; // b7 = lock
|
||||||
|
}
|
||||||
|
FD_LOCK_PARAMS, *PFD_LOCK_PARAMS;
|
||||||
|
|
||||||
|
typedef struct tagFD_LOCK_RESULT
|
||||||
|
{
|
||||||
|
BYTE lock; // b4 = lock
|
||||||
|
}
|
||||||
|
FD_LOCK_RESULT, *PFD_LOCK_RESULT;
|
||||||
|
|
||||||
|
typedef struct tagFD_DUMPREG_RESULT
|
||||||
|
{
|
||||||
|
BYTE pcn0, pcn1, pcn2, pcn3; // present cylinder numbers
|
||||||
|
BYTE srt_hut; // b7-4 = step rate, b3-0 = head unload time
|
||||||
|
BYTE hlt_nd; // b7-1 = head load time, b0 = non-dma mode
|
||||||
|
BYTE sceot; // sector count / end of track
|
||||||
|
BYTE lock_d0123_gap_wgate; // b7 = setting lock, b5-2 = drive selects, b1 = gap 2 (perpendicular), b0 = write gate
|
||||||
|
BYTE eis_efifo_poll_fifothr; // b6 = implied seeks, b5 = fifo enable, b4 = poll disable, b3-0 = fifo threshold
|
||||||
|
BYTE pretrk; // pre-comp start track
|
||||||
|
}
|
||||||
|
FD_DUMPREG_RESULT, *PFD_DUMPREG_RESULT;
|
||||||
|
|
||||||
|
typedef struct tagFD_SECTOR_OFFSET_PARAMS
|
||||||
|
{
|
||||||
|
BYTE sectors; // number of sectors to skip after index
|
||||||
|
}
|
||||||
|
FD_SECTOR_OFFSET_PARAMS, *PFD_SECTOR_OFFSET_PARAMS;
|
||||||
|
|
||||||
|
typedef struct tagFD_SHORT_WRITE_PARAMS
|
||||||
|
{
|
||||||
|
DWORD length; // length to write before interrupting
|
||||||
|
DWORD finetune; // finetune delay in microseconds
|
||||||
|
}
|
||||||
|
FD_SHORT_WRITE_PARAMS, *PFD_SHORT_WRITE_PARAMS;
|
||||||
|
|
||||||
|
typedef struct tagFD_SCAN_PARAMS
|
||||||
|
{
|
||||||
|
BYTE flags; // MFM
|
||||||
|
BYTE head;
|
||||||
|
}
|
||||||
|
FD_SCAN_PARAMS, *PFD_SCAN_PARAMS;
|
||||||
|
|
||||||
|
typedef struct tagFD_SCAN_RESULT
|
||||||
|
{
|
||||||
|
BYTE count; // count of returned headers
|
||||||
|
FD_ID_HEADER Header[]; // array of 'count' id fields
|
||||||
|
}
|
||||||
|
FD_SCAN_RESULT, *PFD_SCAN_RESULT;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct tagFD_TIMED_ID_HEADER
|
||||||
|
{
|
||||||
|
DWORD reltime; // time relative to index (in microseconds)
|
||||||
|
BYTE cyl, head, sector, size;
|
||||||
|
}
|
||||||
|
FD_TIMED_ID_HEADER, *PFD_TIMED_ID_HEADER;
|
||||||
|
|
||||||
|
typedef struct tagFD_TIMED_SCAN_RESULT
|
||||||
|
{
|
||||||
|
BYTE count; // count of returned headers
|
||||||
|
BYTE firstseen; // offset of first sector detected
|
||||||
|
DWORD tracktime; // total time for track (in microseconds)
|
||||||
|
FD_TIMED_ID_HEADER Header[]; // array of 'count' id fields
|
||||||
|
}
|
||||||
|
FD_TIMED_SCAN_RESULT, *PFD_TIMED_SCAN_RESULT;
|
||||||
|
|
||||||
|
typedef struct tagFD_FDC_INFO
|
||||||
|
{
|
||||||
|
BYTE ControllerType; // FDC_TYPE_*
|
||||||
|
BYTE SpeedsAvailable; // FDC_SPEED_* values ORed together
|
||||||
|
|
||||||
|
BYTE BusType;
|
||||||
|
DWORD BusNumber;
|
||||||
|
DWORD ControllerNumber;
|
||||||
|
DWORD PeripheralNumber;
|
||||||
|
}
|
||||||
|
FD_FDC_INFO, *PFD_FDC_INFO;
|
||||||
|
|
||||||
|
typedef struct tagFD_RAW_READ_PARAMS
|
||||||
|
{
|
||||||
|
BYTE flags; // MFM
|
||||||
|
BYTE head, size;
|
||||||
|
}
|
||||||
|
FD_RAW_READ_PARAMS, *PFD_RAW_READ_PARAMS;
|
||||||
|
|
||||||
|
|
||||||
|
#pragma warning(pop)
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
#endif // FDRAWCMD_H
|
||||||
+339
@@ -0,0 +1,339 @@
|
|||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 2, June 1991
|
||||||
|
|
||||||
|
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The licenses for most software are designed to take away your
|
||||||
|
freedom to share and change it. By contrast, the GNU General Public
|
||||||
|
License is intended to guarantee your freedom to share and change free
|
||||||
|
software--to make sure the software is free for all its users. This
|
||||||
|
General Public License applies to most of the Free Software
|
||||||
|
Foundation's software and to any other program whose authors commit to
|
||||||
|
using it. (Some other Free Software Foundation software is covered by
|
||||||
|
the GNU Lesser General Public License instead.) You can apply it to
|
||||||
|
your programs, too.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
this service if you wish), that you receive source code or can get it
|
||||||
|
if you want it, that you can change the software or use pieces of it
|
||||||
|
in new free programs; and that you know you can do these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to make restrictions that forbid
|
||||||
|
anyone to deny you these rights or to ask you to surrender the rights.
|
||||||
|
These restrictions translate to certain responsibilities for you if you
|
||||||
|
distribute copies of the software, or if you modify it.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether
|
||||||
|
gratis or for a fee, you must give the recipients all the rights that
|
||||||
|
you have. You must make sure that they, too, receive or can get the
|
||||||
|
source code. And you must show them these terms so they know their
|
||||||
|
rights.
|
||||||
|
|
||||||
|
We protect your rights with two steps: (1) copyright the software, and
|
||||||
|
(2) offer you this license which gives you legal permission to copy,
|
||||||
|
distribute and/or modify the software.
|
||||||
|
|
||||||
|
Also, for each author's protection and ours, we want to make certain
|
||||||
|
that everyone understands that there is no warranty for this free
|
||||||
|
software. If the software is modified by someone else and passed on, we
|
||||||
|
want its recipients to know that what they have is not the original, so
|
||||||
|
that any problems introduced by others will not reflect on the original
|
||||||
|
authors' reputations.
|
||||||
|
|
||||||
|
Finally, any free program is threatened constantly by software
|
||||||
|
patents. We wish to avoid the danger that redistributors of a free
|
||||||
|
program will individually obtain patent licenses, in effect making the
|
||||||
|
program proprietary. To prevent this, we have made it clear that any
|
||||||
|
patent must be licensed for everyone's free use or not licensed at all.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
0. This License applies to any program or other work which contains
|
||||||
|
a notice placed by the copyright holder saying it may be distributed
|
||||||
|
under the terms of this General Public License. The "Program", below,
|
||||||
|
refers to any such program or work, and a "work based on the Program"
|
||||||
|
means either the Program or any derivative work under copyright law:
|
||||||
|
that is to say, a work containing the Program or a portion of it,
|
||||||
|
either verbatim or with modifications and/or translated into another
|
||||||
|
language. (Hereinafter, translation is included without limitation in
|
||||||
|
the term "modification".) Each licensee is addressed as "you".
|
||||||
|
|
||||||
|
Activities other than copying, distribution and modification are not
|
||||||
|
covered by this License; they are outside its scope. The act of
|
||||||
|
running the Program is not restricted, and the output from the Program
|
||||||
|
is covered only if its contents constitute a work based on the
|
||||||
|
Program (independent of having been made by running the Program).
|
||||||
|
Whether that is true depends on what the Program does.
|
||||||
|
|
||||||
|
1. You may copy and distribute verbatim copies of the Program's
|
||||||
|
source code as you receive it, in any medium, provided that you
|
||||||
|
conspicuously and appropriately publish on each copy an appropriate
|
||||||
|
copyright notice and disclaimer of warranty; keep intact all the
|
||||||
|
notices that refer to this License and to the absence of any warranty;
|
||||||
|
and give any other recipients of the Program a copy of this License
|
||||||
|
along with the Program.
|
||||||
|
|
||||||
|
You may charge a fee for the physical act of transferring a copy, and
|
||||||
|
you may at your option offer warranty protection in exchange for a fee.
|
||||||
|
|
||||||
|
2. You may modify your copy or copies of the Program or any portion
|
||||||
|
of it, thus forming a work based on the Program, and copy and
|
||||||
|
distribute such modifications or work under the terms of Section 1
|
||||||
|
above, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) You must cause the modified files to carry prominent notices
|
||||||
|
stating that you changed the files and the date of any change.
|
||||||
|
|
||||||
|
b) You must cause any work that you distribute or publish, that in
|
||||||
|
whole or in part contains or is derived from the Program or any
|
||||||
|
part thereof, to be licensed as a whole at no charge to all third
|
||||||
|
parties under the terms of this License.
|
||||||
|
|
||||||
|
c) If the modified program normally reads commands interactively
|
||||||
|
when run, you must cause it, when started running for such
|
||||||
|
interactive use in the most ordinary way, to print or display an
|
||||||
|
announcement including an appropriate copyright notice and a
|
||||||
|
notice that there is no warranty (or else, saying that you provide
|
||||||
|
a warranty) and that users may redistribute the program under
|
||||||
|
these conditions, and telling the user how to view a copy of this
|
||||||
|
License. (Exception: if the Program itself is interactive but
|
||||||
|
does not normally print such an announcement, your work based on
|
||||||
|
the Program is not required to print an announcement.)
|
||||||
|
|
||||||
|
These requirements apply to the modified work as a whole. If
|
||||||
|
identifiable sections of that work are not derived from the Program,
|
||||||
|
and can be reasonably considered independent and separate works in
|
||||||
|
themselves, then this License, and its terms, do not apply to those
|
||||||
|
sections when you distribute them as separate works. But when you
|
||||||
|
distribute the same sections as part of a whole which is a work based
|
||||||
|
on the Program, the distribution of the whole must be on the terms of
|
||||||
|
this License, whose permissions for other licensees extend to the
|
||||||
|
entire whole, and thus to each and every part regardless of who wrote it.
|
||||||
|
|
||||||
|
Thus, it is not the intent of this section to claim rights or contest
|
||||||
|
your rights to work written entirely by you; rather, the intent is to
|
||||||
|
exercise the right to control the distribution of derivative or
|
||||||
|
collective works based on the Program.
|
||||||
|
|
||||||
|
In addition, mere aggregation of another work not based on the Program
|
||||||
|
with the Program (or with a work based on the Program) on a volume of
|
||||||
|
a storage or distribution medium does not bring the other work under
|
||||||
|
the scope of this License.
|
||||||
|
|
||||||
|
3. You may copy and distribute the Program (or a work based on it,
|
||||||
|
under Section 2) in object code or executable form under the terms of
|
||||||
|
Sections 1 and 2 above provided that you also do one of the following:
|
||||||
|
|
||||||
|
a) Accompany it with the complete corresponding machine-readable
|
||||||
|
source code, which must be distributed under the terms of Sections
|
||||||
|
1 and 2 above on a medium customarily used for software interchange; or,
|
||||||
|
|
||||||
|
b) Accompany it with a written offer, valid for at least three
|
||||||
|
years, to give any third party, for a charge no more than your
|
||||||
|
cost of physically performing source distribution, a complete
|
||||||
|
machine-readable copy of the corresponding source code, to be
|
||||||
|
distributed under the terms of Sections 1 and 2 above on a medium
|
||||||
|
customarily used for software interchange; or,
|
||||||
|
|
||||||
|
c) Accompany it with the information you received as to the offer
|
||||||
|
to distribute corresponding source code. (This alternative is
|
||||||
|
allowed only for noncommercial distribution and only if you
|
||||||
|
received the program in object code or executable form with such
|
||||||
|
an offer, in accord with Subsection b above.)
|
||||||
|
|
||||||
|
The source code for a work means the preferred form of the work for
|
||||||
|
making modifications to it. For an executable work, complete source
|
||||||
|
code means all the source code for all modules it contains, plus any
|
||||||
|
associated interface definition files, plus the scripts used to
|
||||||
|
control compilation and installation of the executable. However, as a
|
||||||
|
special exception, the source code distributed need not include
|
||||||
|
anything that is normally distributed (in either source or binary
|
||||||
|
form) with the major components (compiler, kernel, and so on) of the
|
||||||
|
operating system on which the executable runs, unless that component
|
||||||
|
itself accompanies the executable.
|
||||||
|
|
||||||
|
If distribution of executable or object code is made by offering
|
||||||
|
access to copy from a designated place, then offering equivalent
|
||||||
|
access to copy the source code from the same place counts as
|
||||||
|
distribution of the source code, even though third parties are not
|
||||||
|
compelled to copy the source along with the object code.
|
||||||
|
|
||||||
|
4. You may not copy, modify, sublicense, or distribute the Program
|
||||||
|
except as expressly provided under this License. Any attempt
|
||||||
|
otherwise to copy, modify, sublicense or distribute the Program is
|
||||||
|
void, and will automatically terminate your rights under this License.
|
||||||
|
However, parties who have received copies, or rights, from you under
|
||||||
|
this License will not have their licenses terminated so long as such
|
||||||
|
parties remain in full compliance.
|
||||||
|
|
||||||
|
5. You are not required to accept this License, since you have not
|
||||||
|
signed it. However, nothing else grants you permission to modify or
|
||||||
|
distribute the Program or its derivative works. These actions are
|
||||||
|
prohibited by law if you do not accept this License. Therefore, by
|
||||||
|
modifying or distributing the Program (or any work based on the
|
||||||
|
Program), you indicate your acceptance of this License to do so, and
|
||||||
|
all its terms and conditions for copying, distributing or modifying
|
||||||
|
the Program or works based on it.
|
||||||
|
|
||||||
|
6. Each time you redistribute the Program (or any work based on the
|
||||||
|
Program), the recipient automatically receives a license from the
|
||||||
|
original licensor to copy, distribute or modify the Program subject to
|
||||||
|
these terms and conditions. You may not impose any further
|
||||||
|
restrictions on the recipients' exercise of the rights granted herein.
|
||||||
|
You are not responsible for enforcing compliance by third parties to
|
||||||
|
this License.
|
||||||
|
|
||||||
|
7. If, as a consequence of a court judgment or allegation of patent
|
||||||
|
infringement or for any other reason (not limited to patent issues),
|
||||||
|
conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot
|
||||||
|
distribute so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you
|
||||||
|
may not distribute the Program at all. For example, if a patent
|
||||||
|
license would not permit royalty-free redistribution of the Program by
|
||||||
|
all those who receive copies directly or indirectly through you, then
|
||||||
|
the only way you could satisfy both it and this License would be to
|
||||||
|
refrain entirely from distribution of the Program.
|
||||||
|
|
||||||
|
If any portion of this section is held invalid or unenforceable under
|
||||||
|
any particular circumstance, the balance of the section is intended to
|
||||||
|
apply and the section as a whole is intended to apply in other
|
||||||
|
circumstances.
|
||||||
|
|
||||||
|
It is not the purpose of this section to induce you to infringe any
|
||||||
|
patents or other property right claims or to contest validity of any
|
||||||
|
such claims; this section has the sole purpose of protecting the
|
||||||
|
integrity of the free software distribution system, which is
|
||||||
|
implemented by public license practices. Many people have made
|
||||||
|
generous contributions to the wide range of software distributed
|
||||||
|
through that system in reliance on consistent application of that
|
||||||
|
system; it is up to the author/donor to decide if he or she is willing
|
||||||
|
to distribute software through any other system and a licensee cannot
|
||||||
|
impose that choice.
|
||||||
|
|
||||||
|
This section is intended to make thoroughly clear what is believed to
|
||||||
|
be a consequence of the rest of this License.
|
||||||
|
|
||||||
|
8. If the distribution and/or use of the Program is restricted in
|
||||||
|
certain countries either by patents or by copyrighted interfaces, the
|
||||||
|
original copyright holder who places the Program under this License
|
||||||
|
may add an explicit geographical distribution limitation excluding
|
||||||
|
those countries, so that distribution is permitted only in or among
|
||||||
|
countries not thus excluded. In such case, this License incorporates
|
||||||
|
the limitation as if written in the body of this License.
|
||||||
|
|
||||||
|
9. The Free Software Foundation may publish revised and/or new versions
|
||||||
|
of the General Public License from time to time. Such new versions will
|
||||||
|
be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the Program
|
||||||
|
specifies a version number of this License which applies to it and "any
|
||||||
|
later version", you have the option of following the terms and conditions
|
||||||
|
either of that version or of any later version published by the Free
|
||||||
|
Software Foundation. If the Program does not specify a version number of
|
||||||
|
this License, you may choose any version ever published by the Free Software
|
||||||
|
Foundation.
|
||||||
|
|
||||||
|
10. If you wish to incorporate parts of the Program into other free
|
||||||
|
programs whose distribution conditions are different, write to the author
|
||||||
|
to ask for permission. For software which is copyrighted by the Free
|
||||||
|
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||||
|
make exceptions for this. Our decision will be guided by the two goals
|
||||||
|
of preserving the free status of all derivatives of our free software and
|
||||||
|
of promoting the sharing and reuse of software generally.
|
||||||
|
|
||||||
|
NO WARRANTY
|
||||||
|
|
||||||
|
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||||
|
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||||
|
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||||
|
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||||
|
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||||
|
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||||
|
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||||
|
REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||||
|
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||||
|
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||||
|
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||||
|
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||||
|
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||||
|
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGES.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
convey the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This program 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 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program 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 this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program is interactive, make it output a short notice like this
|
||||||
|
when it starts in an interactive mode:
|
||||||
|
|
||||||
|
Gnomovision version 69, Copyright (C) year name of author
|
||||||
|
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
|
This is free software, and you are welcome to redistribute it
|
||||||
|
under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, the commands you use may
|
||||||
|
be called something other than `show w' and `show c'; they could even be
|
||||||
|
mouse-clicks or menu items--whatever suits your program.
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or your
|
||||||
|
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||||
|
necessary. Here is a sample; alter the names:
|
||||||
|
|
||||||
|
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||||
|
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||||
|
|
||||||
|
<signature of Ty Coon>, 1 April 1989
|
||||||
|
Ty Coon, President of Vice
|
||||||
|
|
||||||
|
This General Public License does not permit incorporating your program into
|
||||||
|
proprietary programs. If your program is a subroutine library, you may
|
||||||
|
consider it more useful to permit linking proprietary applications with the
|
||||||
|
library. If this is what you want to do, use the GNU Lesser General
|
||||||
|
Public License instead of this License.
|
||||||
Reference in New Issue
Block a user