-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #57 from stefanschramm/sharp-mz700
Add support for Sharp MZ-700
- Loading branch information
Showing
14 changed files
with
439 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
include ../Makefile.inc | ||
|
||
all: rl.bin rl.mzf | ||
|
||
%.mzf: %.mzf.asm %.bin | ||
$(Z80_ASM) $< -o $@ | ||
|
||
%.bin: %.bin.asm | ||
$(Z80_ASM) $< -o $@ | ||
|
||
clean: | ||
rm -f *.wav *.bin |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
; retroload.com | ||
; example program for Sharp MZ-700 | ||
; to be built using z80asm | ||
; | ||
; Load: L | ||
; Run: J1200 | ||
; | ||
|
||
OFFSET: equ 0x1200 | ||
|
||
; monitor rom routines | ||
BELL: equ 0x003e | ||
PRINTS: equ 0x0012 | ||
GETL: equ 0x0003 | ||
|
||
org OFFSET | ||
|
||
; program | ||
ld hl, GREETING | ||
call PRINTSTRING | ||
call BELL | ||
call GETL | ||
jp 0x0000 | ||
|
||
PRINTSTRING: | ||
; using our own routine because the monitor's MSG routine ignores the carriage returns | ||
; beginning of string in HL | ||
ld a, (hl) | ||
cp 0 | ||
ret z | ||
push hl | ||
call PRINTS | ||
pop hl | ||
inc hl | ||
jp PRINTSTRING | ||
|
||
GREETING: | ||
dm "\r" | ||
dm "---------------------------------\r" | ||
dm "\r" | ||
dm "RETROLOAD.COM\r" | ||
dm "\r" | ||
dm "EXAMPLE FOR SHARP MZ-700 (BINARY)\r" | ||
dm "\r" | ||
dm "LOADED AND EXECUTED!\r" | ||
dm "\r" | ||
dm "---------------------------------\r" | ||
dm "\r" | ||
dm "PRESS RETURN TO RETURN TO MONITOR\r" | ||
db 0 |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
; retroload.com | ||
; example program for Sharp MZ-700 | ||
; to be built using z80asm | ||
; | ||
; Load: L | ||
; Run: J1200 | ||
; | ||
|
||
OFFSET: equ 0x1200 | ||
|
||
db 0x01 ; Type: MZ-700 binary | ||
dm "RL" | ||
db 0x0d ; string delimiter | ||
dm " " ; pad to 17 bytes including delimiter | ||
dw END - START ; file size | ||
dw OFFSET ; load address | ||
dw OFFSET ; entry address | ||
ds 104, 0x00 ; pad header to 128 bytes | ||
|
||
START: | ||
|
||
incbin "rl.bin" | ||
|
||
END: |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
9 changes: 9 additions & 0 deletions
9
retroload-lib/src/encoding/adapter/sharpmz/SharpMzDefinitions.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import {FlagOptionDefinition} from '../../Options.js'; | ||
|
||
export const sharpmznorepeatOption: FlagOptionDefinition = { | ||
name: 'sharpmznorepeat', | ||
label: 'Don\'t repeat data', | ||
description: 'Don\'t repeat data and header', | ||
common: true, | ||
type: 'bool', | ||
}; |
142 changes: 142 additions & 0 deletions
142
retroload-lib/src/encoding/adapter/sharpmz/SharpMzEncoder.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
import {ByteRecorder, recordByteMsbFirst, recordBytes} from '../ByteRecorder.js'; | ||
import {BufferAccess} from '../../../common/BufferAccess.js'; | ||
import {Oscillator} from '../Oscillator.js'; | ||
import {RecorderInterface} from '../../recorder/RecorderInterface.js'; | ||
|
||
const fLongPulse = 1000; | ||
const fShortPulse = 2000; | ||
|
||
/** | ||
* Encoder for Sharp MZ-700 and similar | ||
* | ||
* https://original.sharpmz.org/mz-700/tapeproc.htm | ||
* https://original.sharpmz.org/mz-700/coremain.htm | ||
* | ||
* Note: The "L" mark after checksums in this documentation seems not to be required. | ||
* | ||
* Repeating the data seems to be optional: If the first recording can be loaded, the rest is ignored. | ||
*/ | ||
export class SharpMzEncoder implements ByteRecorder { | ||
private readonly oscillator: Oscillator; | ||
|
||
public constructor( | ||
private readonly recorder: RecorderInterface, | ||
) { | ||
this.oscillator = new Oscillator(this.recorder); | ||
} | ||
|
||
public begin(): void { | ||
this.oscillator.begin(); | ||
} | ||
|
||
public recordHeader(header: BufferAccess, repeat: boolean = false, shortpilot: boolean = false): void { | ||
const checksum = calculateChecksum(header); | ||
const checksumBuffer = BufferAccess.create(2); | ||
checksumBuffer.writeUint16Be(checksum); | ||
|
||
// LGAP | ||
this.oscillator.recordOscillations(fShortPulse, shortpilot ? 5000 : 22000); // "only 10,000 for the MZ-80B" | ||
|
||
// LTM | ||
this.oscillator.recordOscillations(fLongPulse, 40); | ||
this.oscillator.recordOscillations(fShortPulse, 40); | ||
this.oscillator.recordOscillations(fLongPulse, 1); | ||
|
||
// L | ||
this.oscillator.recordOscillations(fLongPulse, 1); | ||
|
||
// HDR | ||
this.recorder.beginAnnotation('Header Data'); | ||
this.recordBytes(header); | ||
this.recorder.endAnnotation(); | ||
|
||
// CHKH | ||
this.recordBytes(checksumBuffer); | ||
|
||
if (repeat) { | ||
// 256S | ||
this.oscillator.recordOscillations(fShortPulse, 256); | ||
|
||
// HDRC | ||
this.recorder.beginAnnotation('Header Data Repeated'); | ||
this.recordBytes(header); | ||
this.recorder.endAnnotation(); | ||
|
||
// CHKH | ||
this.recordBytes(checksumBuffer); | ||
} | ||
} | ||
|
||
public recordData(data: BufferAccess, repeat: boolean = false): void { | ||
const checksum = calculateChecksum(data); | ||
const checksumBuffer = BufferAccess.create(2); | ||
checksumBuffer.writeUint16Be(checksum); | ||
|
||
// SGAP | ||
this.oscillator.recordOscillations(fShortPulse, 11000); | ||
|
||
// STM | ||
this.oscillator.recordOscillations(fLongPulse, 20); | ||
this.oscillator.recordOscillations(fShortPulse, 20); | ||
this.oscillator.recordOscillations(fLongPulse, 1); | ||
|
||
// L | ||
this.oscillator.recordOscillations(fLongPulse, 1); | ||
|
||
// FILE | ||
this.recorder.beginAnnotation('File Data'); | ||
this.recordBytes(data); | ||
this.recorder.endAnnotation(); | ||
|
||
// CHKF | ||
this.recordBytes(checksumBuffer); | ||
|
||
if (repeat) { | ||
// 256S | ||
this.oscillator.recordOscillations(fShortPulse, 256); | ||
|
||
// FILEC | ||
this.recorder.beginAnnotation('File Data Repeated'); | ||
this.recordBytes(data); | ||
this.recorder.endAnnotation(); | ||
|
||
// CHKF | ||
this.recordBytes(checksumBuffer); | ||
} | ||
} | ||
|
||
public recordBytes(data: BufferAccess): void { | ||
recordBytes(this, data); | ||
} | ||
|
||
public end(): void { | ||
this.oscillator.end(); | ||
} | ||
|
||
public recordByte(byte: number): void { | ||
recordByteMsbFirst(this, byte); | ||
this.oscillator.recordOscillations(fLongPulse, 1); | ||
} | ||
|
||
public recordBit(value: number): void { | ||
if (value) { | ||
this.oscillator.recordOscillations(fLongPulse, 1); | ||
} else { | ||
this.oscillator.recordOscillations(fShortPulse, 1); | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* sum of 1-bits in data | ||
*/ | ||
function calculateChecksum(data: BufferAccess): number { | ||
let bitSum = 0; | ||
for (const byte of data.bytes()) { | ||
for (let i = 0; i < 8; i++) { | ||
bitSum = (bitSum + ((byte >> i) & 1)) & 0xffff; | ||
} | ||
} | ||
|
||
return bitSum; | ||
} |
Oops, something went wrong.