Advertisement
wallyweek

pirata disassembly

Mar 30th, 2021 (edited)
2,424
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. ; Commented (dis)assembly listing of Pirata - https://spectrumcomputing.co.uk/entry/36321/ZX-Spectrum/Pirata
  2. ; Rui Ribeiro - 2021
  3. ;
  4. ; border cyan/red - insert tape to copy
  5. ;                   SPACE to end, jump to save
  6. ;
  7. ; border yellow   - insert blank tape and press 1
  8. ;                   (and some other keys, including space,
  9. ;                   see BIT0KEY)
  10. ;
  11. ; border green    - 1 make another copy
  12. ;                   2 start over
  13. ;
  14. ; FORMAT of tape block in memory from $4000 onwards
  15. ;
  16. ;  BYTE 1 - LSB size of block
  17. ;  BYTE 2 - MSB size of block  
  18. ;  BYTE 3 - flag identifying type of tape block
  19. ;  -------- block of data
  20.  
  21. ; if BYTE1 and BYTE2 = 0, no more blocks, otherwise another block follows
  22.  
  23. ; 171 bytes = 155 bytes + 16 bytes for stack (of which 14 are available)
  24.  
  25. ; ROM CALL - alternate LD_BYTES entry point
  26. ; https://skoolkid.github.io/rom/asm/0556.html
  27. ;
  28. ; for not returning to SA_LD_RET at the end of load.
  29. ; Interrupts must be disabled
  30. ;
  31. ; A' - header block + Z=1
  32. ; IX = start address
  33. ; DE = block length
  34. ;
  35. ; returns from LD_FLAG if different flag
  36. ; returns when SPACE pressed or end of data on tape
  37. ;
  38. ; upon completion:
  39. ;
  40. ; DE = number of bytes loaded + 1
  41. ; IX = IX + number of bytes loaded + 1
  42. ;
  43. LD_BYTES2   EQU $0562
  44.  
  45. ; ROM CALL - LD_FLAG alternate entry point
  46. ;
  47. ; after loading headers and byte of flag
  48. ;
  49. ; if flag was different than 0
  50. ; we need to reenter load routine
  51. ;
  52. LD_FLAG2    EQU $05B6
  53.  
  54. ; ROM CALL - SA-BYTES subroutine
  55. ; https://skoolkid.github.io/rom/asm/04C2.html
  56. ;
  57. ;A  = flag, usually 00 header block, $FF data block
  58. ;DE = block length
  59. ;IX = start address
  60. ;
  61. SA_BYTES    EQU $04C2
  62.  
  63.  
  64.    
  65.                 ;  
  66.         ; entry point of PIRATA MC subroutine
  67.         ; originally stored in a REM statement in BASIC
  68.         ; transfered to $FF54 via LDIR
  69.                 ;
  70.         ; ORG   65364
  71.         ORG     $FF54
  72.  
  73. ;
  74. ; ===========================
  75. ;  Initialisation/setup
  76. ; ===========================
  77. ;
  78. ; Moving stack out of way
  79. ; Disabling interrupts.
  80.    
  81. BEGIN:      LD  SP,$FFFF    ; stack pointer - end of RAM
  82.                     ; should be 0000
  83.                     ; as SP grows downwards
  84.    
  85.         DI          ; DI can be moved to before the SP instruction
  86.                     ; it is only needed the first time
  87.                                         ; more one byte to load
  88.  
  89.  
  90. ;
  91. ; ===========================
  92. ;  Block(s) loading
  93. ; ===========================
  94. ;
  95. ; load blocks from tape
  96. ; until SPACE pressed
  97. ;
  98.  
  99.         LD  IX,$4000    ; beginning of RAM/screen
  100.                     ; "MAINLOOP"
  101.  
  102.                     ; if start from scratch loop
  103.                     ; was coming here instead of at BEGIN
  104.                     ; there would be more 4 bytes of free RAM
  105.  
  106. L_NEXTBLK:  LD  (IX+02),00  ; init flag type of tape block to zero
  107.                     ; it won't be set by code if header block 0
  108.  
  109.         PUSH    IX
  110.         INC IX      ; size of block LSB
  111.         INC IX              ; size of block MSB
  112.         INC IX              ; flag type
  113.                     ; usually 00 for header and FF for data        
  114.  
  115.         LD  A,00        ; header block  - Could be XOR A, one less byte
  116.         LD  DE,BEGIN-0x4000 ; $BF54/48980 max number of bytes
  117.                     ; could be MAINLOOP-0x4000
  118.                     ; for more free bytes
  119.  
  120.         ; set carry flag for LOADing
  121.         SCF
  122.  
  123.         ; setup for the ROM instructions we are skipping
  124.         ; Z'=1, A'=code block flag (0)
  125.         ;
  126.         ; better be 0, because header blocks expect a shorter tone
  127.         ; in the ROM LD_BYTES routine
  128.         ;
  129.         INC D
  130.         EX  AF,AF'
  131.         DEC D
  132.  
  133.         LD  A,$0F       ; border white/MIC off
  134.         OUT ($FE),A    
  135.         ; end of "ROM" code
  136.  
  137.         CALL    $LD_BYTES2      ; load block
  138.         JR  Z,END_LOAD  ; end of tape byte stream
  139.  
  140.         ; read keyboard port $7FFE
  141.                ; select keyboard half row BNM Symbol SPACE
  142.         LD  A,$7F      
  143.         IN  A,($FE)
  144.         RR  A
  145.         JR  NC,SAVE_SECTION ; if bit 0 = 0
  146.                     ; SPACE pressed, finish block(s) loading loop
  147.                     ; and jump to save
  148.  
  149.         ; if this block is executed is because
  150.         ; the block flag is different than 0
  151.         ; though at the LD_BYTES routine point
  152.         ; it is stored now in L (and not A)
  153.                ; (L is used to store/put together the last loaded byte/bits
  154.         ; at LD_BYTES 8-bit loading loop)
  155.  
  156.         LD  (IX-01),L   ; save flag block identifier byte in RAM
  157.                     ; after block size
  158.                     ; IX = first data byte
  159.  
  160.  
  161.         XOR A               ; Z=1
  162.         CALL    $LD_FLAG2   ; force reentry into load tape routine
  163.                                        ; right after where it left
  164.                     ; load entry after flag check.
  165.                                        ;
  166.                     ; delete XOR A and change CALL to
  167.                     ; CALL $05B7
  168.                                        ; less one byte
  169.  
  170. ;
  171. ; ===========================
  172. ;  Loading block housekeeping
  173. ; ===========================
  174. ;
  175. ; Calculate loaded bytes, and store the length.
  176. ; Restore IX.
  177. ; Jump to load another block.
  178. ;
  179.  
  180.  
  181.             ; subtract from max number of bytes / original length
  182.                    ; to get bytes loaded
  183.             ; eg. original DE calling LD_BYTES vs new DE returning from LD_BYTES
  184.             ; DE (length) = original DE - new DE - 1
  185.  
  186. END_LOAD:   LD  HL,BEGIN-0x4000 ; $BF54  max number of bytes
  187.                     ; could be MAINLOOP-0x4000
  188.  
  189.         OR  A       ; carry =0
  190.         SBC HL,DE       ; HL=bytes loaded - HL=HL-DE
  191.  
  192.         PUSH    HL
  193.         POP DE      ; DE=HL=bytes loaded(+checksum)
  194.  
  195.         DEC DE      ; DE=bytes loaded
  196.  
  197.         POP HL      ; POP IX before loading, beginning of block
  198.            
  199.         ; store length in memory of this block, before data loaded
  200.         LD  (HL),E          ; (HL) = size (word) = DE at the beginning of block
  201.         INC HL      ; point to next byte
  202.         LD  (HL),D
  203.  
  204.         DEC IX      ; LD_BYTES loading leaves IX at IX+1, DEC it
  205.         JR  L_NEXTBLK   ; next block
  206.  
  207. ;
  208. ; ===========================
  209. ;  Finished loading all blocks
  210. ; ===========================
  211. ;
  212. ; Execute this code after SPACE is pressed.
  213. ;
  214. ; (Next) block with size of word 0, means END.
  215. ;
  216.  
  217. SAVE_SECTION:   POP HL      ; POP IX value before loading
  218.                     ; (beginning of block)
  219.  
  220.         ; (latter IX) = 0 word, no more blocks
  221.         LD  (HL),00     ; (latter IX) = LSB 0 word
  222.         INC HL      ; point to next byte
  223.         LD  (HL),00     ; (latter IX) = MSB 0 word
  224.                     ; could be XOR A,LD (HL),A,INC HL,LD (HL),A
  225.                     ; less one byte
  226. ;
  227. ; ===========================
  228. ;  Waiting for user input
  229. ; ===========================
  230. ;
  231. ; Border yellow
  232. ; waits for a key for saving loaded blocks.
  233. ;
  234.  
  235.         LD  A,06            ; border yellow
  236.         OUT ($FE),A
  237.  
  238.         CALL    DELAY       ; 0.9 seconds delay
  239.  
  240.         ; wait for a pressed key
  241.         ; works for not only for "1"
  242.                ; but also SPACE, ENTER, P, 0, Q, A, Shift
  243.                ;
  244. BIT0KEY:    XOR A       ; select all keyboard half-rows
  245.         IN  A,($FE)     ; IN A,($00FE)
  246.         RR  A       ; rotate 1 bit to the right
  247.         JR  C,BIT0KEY   ; if bit 0=1 (no key pressed), try again
  248.  
  249. ;
  250. ; =========================
  251. ;  Block(s) saving
  252. ; =========================
  253. ;
  254. ; save all blocks
  255. ; with a delay of 0.9 seconds between them
  256.  
  257. BEGIN_SBLOCK:   LD  IX,$4000    ; first RAM address
  258. NEXT_SBLOCK:    CALL    DELAY  
  259.         LD  A,(IX+00)       ; LSB size of block
  260.         LD  D,(IX+01)       ; MSB size of block
  261.         OR  D
  262.         JR  Z,EXIT_SAVE ; size = 0, jump to FFD2
  263.         LD  E,(IX+00)   ; DE = size of block kept on RAM
  264.         LD  A,(IX+02)   ; A = block flag
  265.                    
  266.                     ; could be
  267.                     ; LD E,(IX+0)
  268.                     ; LD D,(IX+1)
  269.                                        ; LD A,E
  270.                     ; OR D
  271.                     ; JR ....
  272.                                        ; LD A,(IX+2)
  273.                                        ; less 3 bytes
  274.  
  275.         ; Add 3 to get past word block SIZE + flag
  276.         INC IX
  277.         INC IX     
  278.         INC IX
  279.  
  280.         ; IX is now pointing at data to be saved
  281.         ; DE has length of data to be saved
  282.  
  283.         CALL    SA_BYTES    ; CALL  SA_BYTES
  284.                     ; change it to CALL $04C6
  285.                     ; and delete DI - one less byte
  286.                     ; and does not PUSH SA/LD-RET into the stack
  287.                     ; so it does not enable interrupts back.
  288.                     ; As it is, EI is executed at $054F, after
  289.                     ; saving a block
  290.  
  291.                DI                      ; disabling interrupts, enabled in SA/LD-RET
  292.                                        ; returning from SA_BYTES
  293.  
  294.                         ; if an interrupt comes before DI
  295.                     ; it needs 20 bytes stack
  296.                     ; if a interrupt happens and a key is pressed
  297.                     ; machine code will be corrupted
  298.                     ; at the DELAY subroutine
  299.  
  300.                     ; nevertheless, an interrupt happening
  301.                     ; just before DI
  302.                     ; even if not overflowing stack
  303.                     ; there will be data corruption, at least
  304.                     ; 1 or 2 bytes at FRAMES ($5C78)
  305.                     ; (and it happens occasionally)
  306.  
  307.  
  308.         DEC IX      ; IX+1 returned from SA_BYTES needs to be corrected
  309.         JR  NEXT_SBLOCK ; saves next block
  310.  
  311. ;
  312. ; =========================
  313. ;  After Saving all blocks
  314. ; =========================
  315. ;
  316. ; border green
  317. ; Reads keyboard:
  318. ;
  319. ; "1" - saves blocks again
  320. ; "2" - starts from scratch loading
  321.  
  322. EXIT_SAVE:  LD  A,04            ; border green
  323.         OUT ($FE),A
  324.  
  325.         ; read keyboard port $F7FE
  326.         LD  BC,$F7FE    ; keyboard half row 1-5
  327. WAIT_1_2:   IN  A,(C)
  328.         BIT 1,A         ; key "2"
  329.         JP  Z,BEGIN         ; begin from scratch
  330.                     ; ought to be MAINLOOP
  331.  
  332.         BIT 0,A             ; key "1"
  333.         JR  Z,BEGIN_SBLOCK  ; save again another copy
  334.         JR  WAIT_1_2    ; read keyboard port again
  335.  
  336. ;
  337. ; =========================
  338. ;  Delay routine
  339. ; =========================
  340. ;
  341. ; delay of aprox 0.9 seconds
  342.  
  343. DELAY:      LD  BC,$FFFF   
  344. DLOOP:      DEC BC      ; decrement BC $FFFF/65535 times
  345.         LD  A,B     ; till BC=0
  346.         OR  C
  347.         JR  NZ,DLOOP    ; JR if BC not equal 0
  348.         RET
  349.  
  350. ;FFEF       16 bytes at the end of RAM empty
  351. ;               15 bytes for stack from SP, so 14 available without corrupting machine code
  352. ;       (SP should be initialized to 0 and not $FFFF for using the 16 allocated bytes)
  353.        
  354.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement