The snapshot routines
THE 'SNAPSHOT-FILE' UFIA
The following bytes are the last 20 bytes of a snapshot file UFIA.
0052 SNAP_UFIA DEFB 0 Directory description.
0053 DEFM "Snap " File name.
005D DEFB 3 File type.
005E DEFW #0000 File length.
0060 DEFW #0000 File address.
0062 DEFW #0000 Not used with Snap's.
0064 DEFW #FFFF Not used with Snap's.
THE 'NON-MASKABLE INTERRUPT' ROUTINE
This is the third point, from address #0000, at which the DISCiPLE system is
paged in. It is reached either by pressing the 'snapshot' button or when
returning from a CALBAS.
0066 NMI_RAM PUSH AF Save A register.
0067 LD A,(#1DE5)
006A CP #47 Check if returning from a CALBAS.
006C JR NZ,#0074,SNAPSHOT Jump if not returning from a CALBAS.
006E XOR A
006F LD (#1DE5),A Clear CALBAS executing.
0072 POP AF Restore A register and return to the
0073 RET calling routine.
THE 'SNAPSHOT' ROUTINE
When the 'snapshot' button is pressed this routine is executed. By pressing the
keys 1 to 5 a choice between the following options can be made: dump the screen
to the printer small or grey-scale, save the screen to disk, or to save the
complete RAM contents to disk both for the 48K and 128K Spectrums.
0074 SNAPSHOT LD A,R
0076 PUSH AF Save R register and interrupt status.
0077 LD (#1FFE),SP Use 'internal' stack.
007B LD SP,#1FFE
007E LD A,I
0080 PUSH AF Save all registers, starting with I.
0081 PUSH HL
0082 PUSH BC
0083 PUSH DE
0084 EXX Save alternative registerset.
0085 PUSH AF Note, AF is PUSHed again!
0086 PUSH HL So in effect AF' is completely
0087 PUSH BC forgotten.
0088 PUSH DE
0089 PUSH IX Save the index registers.
008B PUSH IY
008D DI This is not necessary, interrupts are
disabled already.
008E LD HL,#01EE,SNAP_EXIT
0091 PUSH HL RETurn address from snapshot.
0092 LD (#0296),SP Store current stackpointer at D_ERR_SP
so an error will activate SNAP_EXIT.
0096 LD BC,#FEFE Keyboard port and CAPS-V I/O address.
0099 IN A,(C)
009B BIT 0,A
009D RET NZ Test for CAPS, RETurn if not pressed.
009E LD B,#F7 Key 1-5 I/O address.
00A0 SNAP_KEYS IN E,(C)
00A2 BIT 0,E CASE key OF
00A4 JP Z,#164C,COPS 1: jump to the smallcopy routine.
00A7 BIT 1,E
00A9 JP Z,#16B2,COPS2 2: jump to the greyscale routine.
00AC LD HL,16384 start of RAM (also start of SCR$).
00AF BIT 2,E
00B1 JR NZ,#00BA,NO_SCREEN 3: Save SCREEN$.
00B3 LD A,7 type=SCR$.
00B5 LD DE,6912 length of SCR$.
00B8 JR #00D8,SNAP_SAVE
00BA NO_SCREEN BIT 3,E
00BC JR NZ,#00C5,NO_SNAP_48 4: 48K Snapshot.
00BE LD A,5 type=48K Snap.
00C0 LD DE,49152 length of 48K RAM.
00C3 JR #00D8,SNAP_SAVE
00C5 NO_SNAP_48 BIT 4,E
00C7 JR Z,#00D0,SNAP_128 5: 128K Snapshot.
00C9 INC A END.
00CA AND #07
00CC OUT (C),A Nice stripes in border.
00CE JR #00A0,SNAP_KEYS Wrong key pressed, try again.
00D0 SNAP_128 LD A,9 Type=128K Snap.
00D2 LD DE,16384 Length of a RAM-page.
00D5 LD HL,49152 Start of a RAM-page.
00D8 SNAP_SAVE LD (#0052),A Store type in snapshot UFIA.
00DB LD (#005E),DE Store length in UFIA.
00DF LD (#0060),HL And the start-address.
00E2 LD B,#FE Key CAPS-V I/O address.
00E4 IN A,(C)
00E6 BIT 0,A
00E8 JR NZ,#00F2,NO_DRV_CHG If CAPS is pressed the Snap goes to
00EA LD A,(#1ACE) the other drive.
00ED XOR #01
00EF LD (#1ACE),A
00F2 NO_DRV_CHG LD A,#40
00F4 CALL #2993,JSCAN_CAT Search first free catalogue entry.
00F7 RET NZ Exit if catalogue full.
00F8 LD A,D Track to A.
00F9 AND #07 Jump if CAT-entry will be located
00FB JR Z,#0102,SNAP_NAME1 on track 0.
The name a snapshot-file is given, depends on the position it's going to occupy in
the directory. When the entry will be located on the first track the names range
from 'Snap A' to 'Snap T', if however the entry will be located on track 1 to 3 the
character after 'Snap' will be the track number. I.e. 'Snap1A' to 'Snap1T' for
track 1, etc. Notice that the character after 'Snap' is never set to a ' '.
00FD ADD A,48 ASCII offset for '0'.
00FF LD (#0057),A Store a 1, 2 or 3 in name-part of UFIA.
0102 SNAP_NAME1 LD L,E Store sector in L.
0103 LD A,(#1DDA) Fetch current control port state.
0106 AND #04
0108 JR NZ,#010D,SNAP_NAME2 Jump if Single Density.
010A SLA L Two entries per sector.
010C DEC L
010D SNAP_NAME2 LD A,(IX+14) Is it the first or second entry in the
0110 ADD A,L CAT-sector.
0111 ADD A,64 Add ASCII 'A' offset.
0113 LD (#0058),A Store 'A' to 'T' in name-part of UFIA.
0116 LD HL,#0052 Copy UFIA to DFCA.
0119 LD DE,#1E05
011C LD BC,20
011F LDIR
0121 CALL #29A8,JOFSM_2 Open the file.
0124 LD HL,#1FEA Copy snap registers to catalogue entry.
0127 LD DE,#1BB2
012A LD BC,22
012D LDIR
012F LD A,(#0052) Get directory description.
0132 CP 9
0134 JP NZ,#01DC,NO_SNAP128 Jump if not a 128K Snapshot.
0137 LD HL,49152 Now the 5 first bytes of the current
013A LD DE,#1BD6 RAM-page are saved in the DISCiPLE RAM
013D LD BC,5 and replaced by the "BRUCE" message.
0140 LDIR This is done to determine the currently
0142 LD HL,#01D7,BRUCE paged in RAM-page.
0145 LD DE,49152
0148 LD BC,5
014B LDIR
014D XOR A Signal '128K ROM bank active'.
014E LD (#1E19),A
0151 CALL #0258,?_ROMBANK Determine current 'main' ROM bank.
0154 JR NZ,#015B,SNAP128_1 Jump if 128K ROM bank.
0156 LD A,#10 Signal '48K ROM bank active'.
0158 LD (#1E19),A
015B SNAP128_1 CALL #027B,REST_PBUF Restore printer buffer contents.
015E LD A,(#1E19)
0161 JR #016B,SNAP128_2
0163 DEFB #00,#00 Unused locations.
THE 'EXIT TO STATEMENT RETURN' ROUTINE
This routine returns to the 'main' ROM statement loop. The ROM error routine uses
it if error messages are to be surpressed.
0165 EXIT_STAT LD HL,#1B7D,STMT_R_1 Return to 'STMT_R_1' in 'main' ROM.
0168 JP #004F,UNPAGE_HL
THE 'SNAPSHOT ROUTINE' CONTINUED
016B SNAP128_2 CALL #003D,RAMPAGE_A Page in current ROM bank & RAM page 0.
The code now tests which screen is active. Because it isn't possible to detect
which is the active screen, the user is consulted. By making nice border stripes
the user is signalled that 'Y' (meaning: yes, screen changed) or 'N' (meaning: no,
screen hasn't changed) has to be pressed.
016E SNAP128_3 LD BC,#DFFE Keyboard port and I/O address for Y-P.
0171 IN E,(C)
0173 BIT 4,E
0175 JR Z,#0186,CHANGED_$ Jump if 'Y' was pressed, screen changed.
0177 LD B,#7F I/O address for B-SPACE.
0179 IN E,(C)
017B BIT 3,E
017D JR Z,#0191,SAME_$ Jump if 'N' was pressed, same screen.
017F INC A
0180 AND #07
0182 OUT (C),A Make nice stripes in border again.
0184 JR #016E,SNAP128_3 Only 'Y' or 'N' is accepted.
0186 CHANGED_$ LD A,(#1E19)
0189 OR #08 Signal 'screen 1'.
018B ?_RAMBANK LD (#1E19),A
018E CALL #003D,RAMPAGE_A Page in active ROM bank and screen.
Now the 'which RAM bank' test is executed. The active RAM bank is determined by
searching which bank has been given the "BRUCE" message.
0191 SAME_$ LD DE,49152 Here the message has been placed.
0194 LD HL,#01D7,BRUCE Message to be found.
0197 LD B,5 There are five bytes in the message.
0199 BRUCE?_1 LD A,(DE)
019A CP (HL)
019B JR Z,#01A3,BRUCE?_2 Jump if characters match.
019D LD A,(#1E19) Otherwise it has to be one of the other
01A0 INC A banks.
01A1 JR #018B,?_RAMBANK
01A3 BRUCE?_2 INC DE
01A4 INC HL
01A5 DJNZ #0199,BRUCE?_1 All five characters have to match.
01A7 LD HL,#1BD6 The active RAM bank has been found,
01AA LD DE,49152 restore the original five bytes.
01AD LD BC,5
01B0 LDIR
01B2 LD A,(#1E19)
01B5 PUSH AF Save the page-configuration byte in the
01B6 CALL #29C3,JSBYT snapshot file.
01B9 AND #F8 Mask RAM bank, start with 0.
01BB LD B,#08 There are eight RAM banks
01BD SAVE_BANK PUSH AF
01BE PUSH BC
01BF CALL #003D,RAMPAGE_A Page in RAM bank.
01C2 LD HL,(#0060)
01C5 LD DE,(#005E)
01C9 CALL #29C9,JHSVBK_2 Save DE bytes starting at address HL.
01CC POP BC
01CD POP AF
01CE INC A Next RAM bank.
01CF DJNZ #01BD,SAVE_BANK Loop for all eight 16K RAM banks.
01D1 POP AF
01D2 CALL #003D,RAMPAGE_A Page in original RAM bank.
01D5 JR #01EB,CLOSE_SNAP
01D7 BRUCE DEFM "BRUCE"
01DC NO_SNAP128 CP 7 Copy the 9 header bytes to the file if
01DE CALL Z,#0D2F,SAVE_HEAD1 it is a SCREEN$.
01E1 LD HL,(#0060)
01E4 LD DE,(#005E)
01E8 CALL #29C9,JHSVBK_2 Save DE bytes starting at address HL.
01EB CLOSE_SNAP JP #2981,JCFSM Close the file.
THE 'SNAP_EXIT' ROUTINE
This routine is used to return to the snapshotted program, whether it has been loaded,
a snapshot was saved or an error occurred.
01EE SNAP_EXIT LD HL,#0000 Clear D_ERR_SP.
01F1 LD (#0296),HL
01F4 DI
01F5 NOP
01F6 NOP
01F7 LD SP,#1FEA
01FA POP IY Restore the index registers.
01FC POP IX
01FE POP DE Restore the alternate registerset.
01FF POP BC
0200 POP HL
0201 POP AF
0202 EXX
0203 CALL #0258,?_ROMBANK Determine current 'main' ROM bank.
0206 JR NZ,#0230,SNAP_EX_3 Jump if 128K ROM bank.
0208 CALL #027B,REST_PBUF
020B POP DE Restore the registerset.
020C POP BC
020D POP HL
020E POP AF
020F LD I,A
0211 CP #00
0213 JR Z,#021B,SNAP_EX_1
0215 CP #3F When the I register doesn't contain #00
0217 JR Z,#021B,SNAP_EX_1 or #3F, it is most likely that the
0219 IM 2 interrupt mode is 2.
021B SNAP_EX_1 LD SP,(#1FFE) Restore stack pointer.
021F POP AF
0220 LD R,A Jump if the interupts were disabled
0222 JP PO,#022C,SNAP_EX_2 when 'SNAPSHOT' was entered.
0225 PUSH HL
0226 LD HL,#004F Otherwise return to snapshotted program
0229 JP #004F,UNPAGE_HL via 'main' ROM "POP HL", "POP AF" and
"EI".
022C SNAP_EX_2 POP AF Return to the instruction before which
022D JP #0050,UNPAGE_1 the snapshot occurred.
This piece of code does almost the same as the above. The only difference is that it
returns to the 128 'main' ROM at a somewhat different address.
0230 SNAP_EX_3 CALL #027B,REST_PBUF
0233 POP DE
0234 POP BC
0235 POP HL
0236 POP AF
0237 LD I,A
0239 CP #00
023B JR Z,#0243,SNAP_EX_4
023D CP #3F
023F JR Z,#0243,SNAP_EX_4
0241 IM 2
0243 SNAP_EX_4 LD SP,(#1FFE)
0247 POP AF
0248 LD R,A
024A JP PO,#0254,SNAP_EX_5
024D PUSH BC
024E LD BC,#007B
0251 JP #0046,UNPAGE_BC
0254 SNAP_EX_5 POP AF
0255 JP #0047,UNPAGE_0
THE 'DETERMINE 128K ROM BANK' SUBROUTINE
This routine determines, by examining the byte at address #0001, which bank of the
128K ROM is selected. Because the DISCiPLE system is currently paged in the 'main'
ROM can't be accessed directly. So a routine, which pages out the DISCiPLE, is
copied to the printer buffer. But first the first 10 bytes of the printer buffer
are saved.
0258 ?_ROMBANK LD HL,23296 Save the 10 bytes needed by the
025B LD DE,#1BE6 subroutine in DISCiPLE RAM.
025E LD BC,10
0261 LDIR
0263 LD HL,#0271,DET_ROM Copy the subroutine to the freed bytes.
0266 LD DE,23296,DET_ROM'
0269 LD BC,10
026C LDIR
026E JP 23296,DET_ROM' Exit via DET_ROM.
This small routine is copied to 23296, it returns with the Zero flag set if address
#0001 in the 'main' ROM contains 175, that is when the 48K ROM bank is paged in.
0271 DET_ROM OUT (187),A Page DISCiPLE out.
0273 LD A,(#0001)
0276 CP 175
0278 IN A,(187) Page DISCiPLE in.
027A RET
THE 'RESTORE PRINTER BUFFER' SUBROUTINE
This subroutine restores the printer buffers 10 bytes which were destroyed by the
'?_ROMBANK' subroutine.
027B REST_PBUF LD HL,#1BE6
027E LD DE,23296
0281 LD BC,10
0284 LDIR
0286 RET