From e7ba568149bf3adf3282308ce57f212d098a414d Mon Sep 17 00:00:00 2001 From: Ivan Izaguirre Date: Mon, 14 Nov 2022 18:47:14 +0100 Subject: [PATCH] Imaginary Fujinet Clock device with prodos datetime format --- README.md | 5 ++++- cardSmartport.go | 9 +++++++-- smartPortFujinetClock.go | 21 +++++++++++++++++++-- traceProDOS.go | 2 +- 4 files changed, 31 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index f9cd4c4..ee2bc90 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,10 @@ Portable emulator of an Apple II+ or //e. Written in Go. - Videx Videoterm 80 column card with the Videx Soft Video Switch (Apple ][+ only) - SwyftCard (Apple //e only) - Useful cards not emulating a real card - - Bootable SmartPort / ProDOS card + - Bootable SmartPort / ProDOS card with the following smartport devices: + - Block device (hard disks) + - Fujinet network device (supports only http(s) with GET and JSON) + - Fujinet clock (not in Fujinet upstream) - VidHd, limited to the ROM signature and SHR as used by Total Replay, only for //e models with 128Kb - FASTChip, limited to what Total Replay needs to set and clear fast mode - Mouse Card, emulates the entry points, not the softswitches. diff --git a/cardSmartport.go b/cardSmartport.go index 5586509..6b05d31 100644 --- a/cardSmartport.go +++ b/cardSmartport.go @@ -132,7 +132,12 @@ func (c *CardSmartPort) exec(call *smartPortCall) uint8 { if unit == 0 { unit = 1 // For unit 0(host) use the first device } - result = c.devices[unit-1].exec(call) + + if unit > len(c.devices) { + result = smartPortErrorNoDevice + } else { + result = c.devices[unit-1].exec(call) + } } if c.trace { @@ -149,7 +154,7 @@ func (c *CardSmartPort) hostStatus(call *smartPortCall) uint8 { } // See http://www.1000bit.it/support/manuali/apple/technotes/smpt/tn.smpt.2.html - c.a.mmu.Poke(dest+0, 0x01) // One device + c.a.mmu.Poke(dest+0, uint8(len(c.devices))) c.a.mmu.Poke(dest+1, 0xff) // No interrupt c.a.mmu.Poke(dest+2, 0x00) c.a.mmu.Poke(dest+3, 0x00) // Unknown manufacturer diff --git a/smartPortFujinetClock.go b/smartPortFujinetClock.go index 4515c73..37cbcd8 100644 --- a/smartPortFujinetClock.go +++ b/smartPortFujinetClock.go @@ -68,13 +68,13 @@ func (d *SmartPortFujinetClock) status(code uint8, dest uint16) uint8 { smartPortStatusCodeTypeRead & smartPortStatusCodeTypeOnline, 0, 0, 0, // Block size is 0 8, 'F', 'N', '_', 'C', 'L', 'O', 'C', 'K', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', - 0x0f, // Type clock. See http://www.1000bit.it/support/manuali/apple/technotes/smpt/tn.smpt.4.html + 0x13, // Type fujinet clock. 0x00, // Subtype 0x00, 0x01, // Firmware version }) case 'T': - // Get time + // Get time and send it in easy to use format now := time.Now() d.host.a.mmu.pokeRange(dest, []uint8{ uint8(now.Year() / 100), @@ -85,6 +85,23 @@ func (d *SmartPortFujinetClock) status(code uint8, dest uint16) uint8 { uint8(now.Minute()), uint8(now.Second()), }) + + case 'P': + // Get time and send it in ProDOS format + // See 6.1 in https://prodos8.com/docs/techref/adding-routines-to-prodos/ + now := time.Now() + + datelo := uint8(now.Day()) + uint8(now.Month())<<5 + datehi := uint8(now.Year()%100)<<1 + uint8(now.Month())>>3 + timelo := uint8(now.Minute()) + timehi := uint8(now.Hour()) + + d.host.a.mmu.pokeRange(dest, []uint8{ + datelo, + datehi, + timelo, + timehi, + }) } return smartPortNoError // The return code is always success diff --git a/traceProDOS.go b/traceProDOS.go index 554b077..23162a4 100644 --- a/traceProDOS.go +++ b/traceProDOS.go @@ -141,7 +141,7 @@ func (t *traceProDOS) dumpMLIReturn() { minute := t.a.mmu.Peek(0xbf92) hour := t.a.mmu.Peek(0xbf93) fmt.Printf("%04v-%02v-%02v %02v:%02v\n", - date>>9+1900, (date>>5)&0x1f, date&0x1f, // Review Y2K + date>>9+1900, (date>>5)&0x0f, date&0x1f, // Review Y2K hour, minute) case 0xc5: // Online dataAddress := t.paramWord(2)