forked from NEO-SPECTRUMAN/SpecEmu
-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathZ80Core.asm
9025 lines (7539 loc) · 234 KB
/
Z80Core.asm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
;############################################################################################
;
; Z80 Emulation Core
; ==================
;
;############################################################################################
; Z80 memory access to DRAM row select
; (addr >> 7) and 7F
;
; 0011 1111 1111 1111
; =
; 0011 1111 1000 0000
.code
Machine_Create PROTO :PTR TMACHINE, :BYTE
Machine_Delete PROTO :PTR TMACHINE
Machine_Switch PROTO :PTR TMACHINE,:PTR TMACHINE
Machine_Create proc uses esi edi ebx,
machine:ptr TMACHINE,
m_type: byte
assume edi:ptr TMACHINE
mov edi, machine
.if edi != 0
memclr edi, sizeof TMACHINE
mov al, m_type
mov HardwareMode, al
mov esi, AllocMem (16384 * 8)
.if esi != 0
lea ebx, [edi].bank_ptrs
mov [edi].bank5, esi ; ptr to bank 5 is also pointer to mem block for Free()
mov [ebx][5*4], esi
lea esi, [esi+16384]
mov [edi].bank2, esi
mov [ebx][2*4], esi
lea esi, [esi+16384]
mov [edi].bank0, esi
mov [ebx][0*4], esi
lea esi, [esi+16384]
mov [edi].bank1, esi
mov [ebx][1*4], esi
lea esi, [esi+16384]
mov [edi].bank3, esi
mov [ebx][3*4], esi
lea esi, [esi+16384]
mov [edi].bank4, esi
mov [ebx][4*4], esi
lea esi, [esi+16384]
mov [edi].bank6, esi
mov [ebx][6*4], esi
lea esi, [esi+16384]
mov [edi].bank7, esi
mov [ebx][7*4], esi
return True
.endif
.endif
return False
assume edi:nothing
Machine_Create endp
Machine_Delete proc uses esi edi ebx,
machine:PTR TMACHINE
assume edi:ptr TMACHINE
mov edi, machine
.if edi != 0
invoke FreeMemory, [edi].bank5
.endif
ret
assume edi:nothing
Machine_Delete endp
Machine_Switch proc uses esi edi ebx,
machine1:PTR TMACHINE,
machine2:PTR TMACHINE
mov esi, machine1
mov edi, machine2
mov ebx, sizeof TMACHINE
@@: mov al, [esi]
mov ah, [edi]
mov [esi], ah
mov [edi], al
inc esi
inc edi
dec ebx
jnz @B
ret
Machine_Switch endp
.data
align 4
DRAMFADEMASK dd 01110111110110111011011111101110b ; 11111111 11111111 11111111 11111111b
.code
align 16
DRAM_Fade proc uses esi edi ebx
local dram_fade_msg: BOOL
mov dram_fade_msg, FALSE
; increment all refresh counters
lea esi, currentMachine.refresh_counters
mov eax, 01010101h
mov ecx, 128/4
@@: add [esi], eax
add esi, 4
dec ecx
jnz @B
DRAM_FRAMES_2_FADE equ 50
lea esi, currentMachine.refresh_counters
xor edx, edx ; byte offset into DRAM; advances 128 bytes per RAS row
SETLOOP 128 ; 128 RAS rows per DRAM
.if byte ptr [esi] >= DRAM_FRAMES_2_FADE
mov dram_fade_msg, TRUE
xor ebx, ebx
; for all 8 RAM pages
.while ebx < 8
; if this RAM is fadeable
.if [currentMachine.DoesDRAMFade+ebx*4]
mov edi, [currentMachine.bank_ptrs+ebx*4]
add edi, edx
mov eax, DRAMFADEMASK
; fade all 128 bytes in this RAM row
mov ecx, (128/4)/4
@@: and dword ptr [edi], eax
and dword ptr [edi+4], eax
and dword ptr [edi+8], eax
and dword ptr [edi+12], eax
add edi, 4*4
dec ecx
jnz @B
.endif
add ebx, 1
.endw
.endif
add esi, 1
add edx, 128 ; advance 128 bytes to next RAS row
ENDLOOP
rol DRAMFADEMASK, 1
IFDEF DEBUGBUILD
.if dram_fade_msg == TRUE
ADDMESSAGE "DRAM Fade"
.endif
ENDIF
ret
DRAM_Fade endp
Clear_Mem_Map proc
memclr addr Map_Memory, 65536
ret
Clear_Mem_Map endp
.const
szMapFilter db "Map files (*.map)",0,"*.map",0, 0
.data
align 16
Z80JumpTable dd Op00,Op01,Op02,Op03,Op04,Op05,Op06,Op07
dd Op08,Op09,Op0A,Op0B,Op0C,Op0D,Op0E,Op0F
dd Op10,Op11,Op12,Op13,Op14,Op15,Op16,Op17
dd Op18,Op19,Op1A,Op1B,Op1C,Op1D,Op1E,Op1F
dd Op20,Op21,Op22,Op23,Op24,Op25,Op26,Op27
dd Op28,Op29,Op2A,Op2B,Op2C,Op2D,Op2E,Op2F
dd Op30,Op31,Op32,Op33,Op34,Op35,Op36,Op37
dd Op38,Op39,Op3A,Op3B,Op3C,Op3D,Op3E,Op3F
dd Op40,Op41,Op42,Op43,Op44,Op45,Op46,Op47
dd Op48,Op49,Op4A,Op4B,Op4C,Op4D,Op4E,Op4F
dd Op50,Op51,Op52,Op53,Op54,Op55,Op56,Op57
dd Op58,Op59,Op5A,Op5B,Op5C,Op5D,Op5E,Op5F
dd Op60,Op61,Op62,Op63,Op64,Op65,Op66,Op67
dd Op68,Op69,Op6A,Op6B,Op6C,Op6D,Op6E,Op6F
dd Op70,Op71,Op72,Op73,Op74,Op75,Op76,Op77
dd Op78,Op79,Op7A,Op7B,Op7C,Op7D,Op7E,Op7F
dd Op80,Op81,Op82,Op83,Op84,Op85,Op86,Op87
dd Op88,Op89,Op8A,Op8B,Op8C,Op8D,Op8E,Op8F
dd Op90,Op91,Op92,Op93,Op94,Op95,Op96,Op97
dd Op98,Op99,Op9A,Op9B,Op9C,Op9D,Op9E,Op9F
dd OpA0,OpA1,OpA2,OpA3,OpA4,OpA5,OpA6,OpA7
dd OpA8,OpA9,OpAA,OpAB,OpAC,OpAD,OpAE,OpAF
dd OpB0,OpB1,OpB2,OpB3,OpB4,OpB5,OpB6,OpB7
dd OpB8,OpB9,OpBA,OpBB,OpBC,OpBD,OpBE,OpBF
dd OpC0,OpC1,OpC2,OpC3,OpC4,OpC5,OpC6,OpC7
dd OpC8,OpC9,OpCA,OpCB,OpCC,OpCD,OpCE,OpCF
dd OpD0,OpD1,OpD2,OpD3,OpD4,OpD5,OpD6,OpD7
dd OpD8,OpD9,OpDA,OpDB,OpDC,OpDD,OpDE,OpDF
dd OpE0,OpE1,OpE2,OpE3,OpE4,OpE5,OpE6,OpE7
dd OpE8,OpE9,OpEA,OpEB,OpEC,OpED,OpEE,OpEF
dd OpF0,OpF1,OpF2,OpF3,OpF4,OpF5,OpF6,OpF7
dd OpF8,OpF9,OpFA,OpFB,OpFC,OpFD,OpFE,OpFF
Z80JumpTable_DD dd Op00,Op01,Op02,Op03,Op04,Op05,Op06,Op07
dd Op08,OpDD09,Op0A,Op0B,Op0C,Op0D,Op0E,Op0F
dd Op10,Op11,Op12,Op13,Op14,Op15,Op16,Op17
dd Op18,OpDD19,Op1A,Op1B,Op1C,Op1D,Op1E,Op1F
dd Op20,OpDD21,OpDD22,OpDD23,OpDD24,OpDD25,OpDD26,Op27
dd Op28,OpDD29,OpDD2A,OpDD2B,OpDD2C,OpDD2D,OpDD2E,Op2F
dd Op30,Op31,Op32,Op33,OpDD34,OpDD35,OpDD36,Op37
dd Op38,OpDD39,Op3A,Op3B,Op3C,Op3D,Op3E,Op3F
dd Op40,Op41,Op42,Op43,OpDD44,OpDD45,OpDD46,Op47
dd Op48,Op49,Op4A,Op4B,OpDD4C,OpDD4D,OpDD4E,Op4F
dd Op50,Op51,Op52,Op53,OpDD54,OpDD55,OpDD56,Op57
dd Op58,Op59,Op5A,Op5B,OpDD5C,OpDD5D,OpDD5E,Op5F
dd OpDD60,OpDD61,OpDD62,OpDD63,Op64,OpDD65,OpDD66,OpDD67
dd OpDD68,OpDD69,OpDD6A,OpDD6B,OpDD6C,Op6D,OpDD6E,OpDD6F
dd OpDD70,OpDD71,OpDD72,OpDD73,OpDD74,OpDD75,Op76,OpDD77
dd Op78,Op79,Op7A,Op7B,OpDD7C,OpDD7D,OpDD7E,Op7F
dd Op80,Op81,Op82,Op83,OpDD84,OpDD85,OpDD86,Op87
dd Op88,Op89,Op8A,Op8B,OpDD8C,OpDD8D,OpDD8E,Op8F
dd Op90,Op91,Op92,Op93,OpDD94,OpDD95,OpDD96,Op97
dd Op98,Op99,Op9A,Op9B,OpDD9C,OpDD9D,OpDD9E,Op9F
dd OpA0,OpA1,OpA2,OpA3,OpDDA4,OpDDA5,OpDDA6,OpA7
dd OpA8,OpA9,OpAA,OpAB,OpDDAC,OpDDAD,OpDDAE,OpAF
dd OpB0,OpB1,OpB2,OpB3,OpDDB4,OpDDB5,OpDDB6,OpB7
dd OpB8,OpB9,OpBA,OpBB,OpDDBC,OpDDBD,OpDDBE,OpBF
dd OpC0,OpC1,OpC2,OpC3,OpC4,OpC5,OpC6,OpC7
dd OpC8,OpC9,OpCA,OpCB,OpCC,OpCD,OpCE,OpCF
dd OpD0,OpD1,OpD2,OpD3,OpD4,OpD5,OpD6,OpD7
dd OpD8,OpD9,OpDA,OpDB,OpDC,OpDD,OpDE,OpDF
dd OpE0,OpDDE1,OpE2,OpDDE3,OpE4,OpDDE5,OpE6,OpE7
dd OpE8,OpDDE9,OpEA,OpEB,OpEC,OpED,OpEE,OpEF
dd OpF0,OpF1,OpF2,OpF3,OpF4,OpF5,OpF6,OpF7
dd OpF8,OpDDF9,OpFA,OpFB,OpFC,OpFD,OpFE,OpFF
Z80JumpTable_FD dd Op00,Op01,Op02,Op03,Op04,Op05,Op06,Op07
dd Op08,OpFD09,Op0A,Op0B,Op0C,Op0D,Op0E,Op0F
dd Op10,Op11,Op12,Op13,Op14,Op15,Op16,Op17
dd Op18,OpFD19,Op1A,Op1B,Op1C,Op1D,Op1E,Op1F
dd Op20,OpFD21,OpFD22,OpFD23,OpFD24,OpFD25,OpFD26,Op27
dd Op28,OpFD29,OpFD2A,OpFD2B,OpFD2C,OpFD2D,OpFD2E,Op2F
dd Op30,Op31,Op32,Op33,OpFD34,OpFD35,OpFD36,Op37
dd Op38,OpFD39,Op3A,Op3B,Op3C,Op3D,Op3E,Op3F
dd Op40,Op41,Op42,Op43,OpFD44,OpFD45,OpFD46,Op47
dd Op48,Op49,Op4A,Op4B,OpFD4C,OpFD4D,OpFD4E,Op4F
dd Op50,Op51,Op52,Op53,OpFD54,OpFD55,OpFD56,Op57
dd Op58,Op59,Op5A,Op5B,OpFD5C,OpFD5D,OpFD5E,Op5F
dd OpFD60,OpFD61,OpFD62,OpFD63,Op64,OpFD65,OpFD66,OpFD67
dd OpFD68,OpFD69,OpFD6A,OpFD6B,OpFD6C,Op6D,OpFD6E,OpFD6F
dd OpFD70,OpFD71,OpFD72,OpFD73,OpFD74,OpFD75,Op76,OpFD77
dd Op78,Op79,Op7A,Op7B,OpFD7C,OpFD7D,OpFD7E,Op7F
dd Op80,Op81,Op82,Op83,OpFD84,OpFD85,OpFD86,Op87
dd Op88,Op89,Op8A,Op8B,OpFD8C,OpFD8D,OpFD8E,Op8F
dd Op90,Op91,Op92,Op93,OpFD94,OpFD95,OpFD96,Op97
dd Op98,Op99,Op9A,Op9B,OpFD9C,OpFD9D,OpFD9E,Op9F
dd OpA0,OpA1,OpA2,OpA3,OpFDA4,OpFDA5,OpFDA6,OpA7
dd OpA8,OpA9,OpAA,OpAB,OpFDAC,OpFDAD,OpFDAE,OpAF
dd OpB0,OpB1,OpB2,OpB3,OpFDB4,OpFDB5,OpFDB6,OpB7
dd OpB8,OpB9,OpBA,OpBB,OpFDBC,OpFDBD,OpFDBE,OpBF
dd OpC0,OpC1,OpC2,OpC3,OpC4,OpC5,OpC6,OpC7
dd OpC8,OpC9,OpCA,OpCB,OpCC,OpCD,OpCE,OpCF
dd OpD0,OpD1,OpD2,OpD3,OpD4,OpD5,OpD6,OpD7
dd OpD8,OpD9,OpDA,OpDB,OpDC,OpDD,OpDE,OpDF
dd OpE0,OpFDE1,OpE2,OpFDE3,OpE4,OpFDE5,OpE6,OpE7
dd OpE8,OpFDE9,OpEA,OpEB,OpEC,OpED,OpEE,OpEF
dd OpF0,OpF1,OpF2,OpF3,OpF4,OpF5,OpF6,OpF7
dd OpF8,OpFDF9,OpFA,OpFB,OpFC,OpFD,OpFE,OpFF
Z80JumpTable_ED dd EDRet,EDRet,EDRet,EDRet,EDRet,EDRet,EDRet,EDRet
dd EDRet,EDRet,EDRet,EDRet,EDRet,EDRet,EDRet,EDRet
dd EDRet,EDRet,EDRet,EDRet,EDRet,EDRet,EDRet,EDRet
dd EDRet,EDRet,EDRet,EDRet,EDRet,EDRet,EDRet,EDRet
dd EDRet,EDRet,EDRet,EDRet,EDRet,EDRet,EDRet,EDRet
dd EDRet,EDRet,EDRet,EDRet,EDRet,EDRet,EDRet,EDRet
dd EDRet,EDRet,EDRet,EDRet,EDRet,EDRet,EDRet,EDRet
dd EDRet,EDRet,EDRet,EDRet,EDRet,EDRet,EDRet,EDRet
dd OpED40,OpED41,OpED42,OpED43,OpED44,OpED45,OpED46,OpED47
dd OpED48,OpED49,OpED4A,OpED4B,OpED4C,OpED4D,OpED4E,OpED4F
dd OpED50,OpED51,OpED52,OpED53,OpED54,OpED55,OpED56,OpED57
dd OpED58,OpED59,OpED5A,OpED5B,OpED5C,OpED5D,OpED5E,OpED5F
dd OpED60,OpED61,OpED62,OpED63,OpED64,OpED65,OpED66,OpED67
dd OpED68,OpED69,OpED6A,OpED6B,OpED6C,OpED6D,OpED6E,OpED6F
dd OpED70,OpED71,OpED72,OpED73,OpED74,OpED75,OpED76,OpED77
dd OpED78,OpED79,OpED7A,OpED7B,OpED7C,OpED7D,OpED7E,OpED7F
dd OpED80,OpED81,OpED82,OpED83,OpED84,OpED85,OpED86,OpED87
dd OpED88,OpED89,OpED8A,OpED8B,OpED8C,OpED8D,OpED8E,OpED8F
dd OpED90,OpED91,OpED92,OpED93,OpED94,OpED95,OpED96,OpED97
dd OpED98,OpED99,OpED9A,OpED9B,OpED9C,OpED9D,OpED9E,OpED9F
dd OpEDA0,OpEDA1,OpEDA2,OpEDA3,OpEDA4,OpEDA5,OpEDA6,OpEDA7
dd OpEDA8,OpEDA9,OpEDAA,OpEDAB,OpEDAC,OpEDAD,OpEDAE,OpEDAF
dd OpEDB0,OpEDB1,OpEDB2,OpEDB3,OpEDB4,OpEDB5,OpEDB6,OpEDB7
dd OpEDB8,OpEDB9,OpEDBA,OpEDBB,OpEDBC,OpEDBD,OpEDBE,OpEDBF
dd OpEDC0,OpEDC1,OpEDC2,OpEDC3,OpEDC4,OpEDC5,OpEDC6,OpEDC7
dd OpEDC8,OpEDC9,OpEDCA,OpEDCB,OpEDCC,OpEDCD,OpEDCE,OpEDCF
dd OpEDD0,OpEDD1,OpEDD2,OpEDD3,OpEDD4,OpEDD5,OpEDD6,OpEDD7
dd OpEDD8,OpEDD9,OpEDDA,OpEDDB,OpEDDC,OpEDDD,OpEDDE,OpEDDF
dd OpEDE0,OpEDE1,OpEDE2,OpEDE3,OpEDE4,OpEDE5,OpEDE6,OpEDE7
dd OpEDE8,OpEDE9,OpEDEA,OpEDEB,OpEDEC,OpEDED,OpEDEE,OpEDEF
dd OpEDF0,OpEDF1,OpEDF2,OpEDF3,OpEDF4,OpEDF5,OpEDF6,OpEDF7
dd OpEDF8,OpEDF9,OpEDFA,OpEDFB,OpEDFC,OpEDFD,OpEDFE,OpEDFF
CBFuncJumpTable dd CB_RLC, CB_RRC, CB_RL, CB_RR
dd CB_SLA, CB_SRA, CB_SLL, CB_SRL
dd CB_BIT0,CB_BIT1,CB_BIT2,CB_BIT3
dd CB_BIT4,CB_BIT5,CB_BIT6,CB_BIT7
dd CB_RES0,CB_RES1,CB_RES2,CB_RES3
dd CB_RES4,CB_RES5,CB_RES6,CB_RES7
dd CB_SET0,CB_SET1,CB_SET2,CB_SET3
dd CB_SET4,CB_SET5,CB_SET6,CB_SET7
;############################################################################################
.data?
align 16
; Complete Z80 system data starts here
; ====================================
Z80SYSTEMSTART LABEL BYTE
; Z80 Memory Area ; MUST remain @ Z80SYSTEMSTART for 'Compare Snapshot Image' function!!!
; ===============
; currently in "Vars.asm"
align 16
currentMachine TMACHINE <>
RegisterBase equ <currentMachine>
z80registers equ <currentMachine>
CM equ <currentMachine>
align 16
; Fullspeed variables
; test for any TRUE value with ".if FULLSPEEDMODE != NULL"...
FULLSPEEDMODE LABEL DWORD ; 4 bytes, any of which cause fullspeed emulation
MAXIMUMSPEED BYTE ? ; TRUE if emulator at max speed mode
MAXIMUMDISKSPEED BYTE ? ; frames counter for max disk speed loading
MAXIMUMAUTOLOADTYPE BYTE ? ; TRUE when the 'phantom typist' is typing LOAD "" for tape autoloads
_max_pad_ BYTE ?
FramesPerSecond DWORD ? ; FPS counter
GlobalFramesCounter DWORD ? ; increments every frame
Timer_1s_tickcount DWORD ? ; increments every WM_TIMER message (1 second intervals)
uSpeechTimer DWORD ?
RealTapeMode BYTE ? ; using real tape input
AYTimer BYTE ?
SampleTimer BYTE ?
RealTapeTimer BYTE ?
TapePlaying BYTE ? ; TRUE if virtual tape is playing
HardReset BYTE ?
DoingBitTest BYTE ?
RETCounter BYTE ?
align 16
; Sound chip registers
AYBase LABEL BYTE ; base address of AY registers and variables
SCTone_A LABEL WORD
AY_ToneA equ 0
SCRegister0 BYTE ?
SCRegister1 BYTE ?
SCTone_B LABEL WORD
AY_ToneB equ 2
SCRegister2 BYTE ?
SCRegister3 BYTE ?
SCTone_C LABEL WORD
AY_ToneC equ 4
SCRegister4 BYTE ?
SCRegister5 BYTE ?
AY_R6 equ 6
SCRegister6 BYTE ?
AY_R7 equ 7
SCRegister7 BYTE ?
AY_R8 equ 8
SCRegister8 BYTE ?
AY_R9 equ 9
SCRegister9 BYTE ?
AY_R10 equ 10
SCRegister10 BYTE ?
SCEnvPeriod LABEL WORD
AY_EnvPeriod equ 11
SCRegister11 BYTE ?
SCRegister12 BYTE ?
AY_R13 equ 13
SCRegister13 BYTE ?
SCRegister14 BYTE ?
SCRegister15 BYTE ?
AY_FinalChanA equ 16
FinalChanA WORD ?
AY_FinalChanB equ 18
FinalChanB WORD ?
AY_FinalChanC equ 20
FinalChanC WORD ?
AY_ChACounter equ 22
ChACounter WORD ?
AY_ChBCounter equ 24
ChBCounter WORD ?
AY_ChCCounter equ 26
ChCCounter WORD ?
AY_EnvCounter equ 28
EnvCounter WORD ?
AY_NoiseOutput equ 30
NoiseOutput BYTE ?
AY_WhiteNoiseCounter equ 31
WhiteNoiseCounter BYTE ?
AY_InternalR6 equ 32
InternalR6 BYTE ?
AY_ChAOutput equ 33
ChAOutput BYTE ?
AY_ChBOutput equ 34
ChBOutput BYTE ?
AY_ChCOutput equ 35
ChCOutput BYTE ?
AY_EnvelopeClock equ 36
EnvelopeClock BYTE ?
AY_EnvMode equ 37
EnvMode BYTE ?
ay_pad1 BYTE ? ; 38
ay_pad2 BYTE ? ; 39
AY_RandomSeed equ 40
RandomSeed DWORD ?
AY_Total_ChanA equ 44
Total_ChanA DWORD ?
AY_Total_ChanB equ 48
Total_ChanB DWORD ?
AY_Total_ChanC equ 52
Total_ChanC DWORD ?
AY_EnvVolume equ 56
EnvVolume DWORD ?
AY_SampleCounter equ 60
SampleCounter DWORD ?
BeeperSubTotal DWORD ?
BeeperSubCount WORD ?
BeepVal WORD ?
EarVal WORD ?
BeepHold WORD ?
MICVal BYTE ?
BeeperSub BYTE ?
; EnvMode equates:
RESETENUM
ENUM env_DECAY, env_ATTACK, env_OFF, env_HOLD
SCSelectReg BYTE ? ; sound chip register select (last OUT to FFFD)
Last7FFDWrite BYTE ?
Last1FFDWrite BYTE ?
Last_FE_Write BYTE ?
AYShadowRegisters BYTE 16 dup (?) ; 16 AY registers
AY_FloatingRegister BYTE ? ; "floating" AY register
SaveHardwareMode BYTE ? ; backup of HardwareMode var stored in memory snapshot
; Complete Z80 system data ends here
; ==================================
Z80SYSTEMEND LABEL BYTE
Z80SYSTEMSIZE EQU Z80SYSTEMEND-Z80SYSTEMSTART ; size of data for mem snapshot
Z80SystemSnapshot BYTE Z80SYSTEMSIZE dup (?) ; memory snapshot area
; required padding
DWORD 8 DUP (?)
;############################################################################################
; variables not to be stored in the system snapshot
align 16
PortTotalTStates DWORD ? ; updated with greatest TStates count for all accessed ports
PortDeviceType DWORD ? ; identifier for last accessed device port
PortReadAddress WORD ? ; last port address read
PortWriteAddress WORD ? ; last port address written to
PortReadByte BYTE ? ; byte read from a port
PortWriteByte BYTE ? ; byte being written to a port
; port access values
PORT_NONE equ 0
PORT_READ equ 1
PORT_WRITE equ 2
Floating_Bus_Read BYTE ?
MemorySnapshotValid BYTE ? ; TRUE = Got a valid memory snapshot
CPU_Speed BYTE ?
MuteSound BYTE ?
TPC_History struct
_Offset DWORD ?
Table DWORD 256 dup (?)
TPC_History ends
align 16
PC_History TPC_History <>
;############################################################################################
.code
Save_Memory_Map proc
local ofn: OPENFILENAME,
mapFH: DWORD
local tempfile [MAX_PATH]: BYTE
mov tempfile[0], 0
invoke SaveFileName, hWnd, SADD ("Save Memory Map"), addr szMapFilter, addr ofn, addr tempfile, addr MAPExt, 0
.if eax != 0
invoke RemoveExtension, addr tempfile
ADDEXTENSION addr tempfile, addr MAPExt
mov mapFH, $fnc (CreateFile, addr tempfile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL)
.if mapFH != INVALID_HANDLE_VALUE
invoke WriteFile, mapFH, addr Map_Memory, 65536, addr BytesSaved, NULL
invoke CloseHandle, mapFH
.else
invoke ShowMessageBox, hWnd, SADD ("Unable to write Map file"), addr szWindowName, MB_OK or MB_ICONERROR
.endif
.endif
ret
Save_Memory_Map endp
align 16
Add_PC_History: push esi
lea esi, PC_History
push eax
movzx eax, PrevzPC
push ecx
mov ecx, [esi].TPC_History._Offset
.if eax != [[esi].TPC_History.Table+ecx*4]
inc cl
mov [[esi].TPC_History.Table+ecx*4], eax
mov [esi].TPC_History._Offset, ecx
.endif
pop ecx
pop eax
pop esi
ret
ADD_PC_HISTORY macro
call Add_PC_History
endm
SaveMemorySnapshot proc hParent: HWND
.if MemorySnapshotValid
invoke ShowMessageBox, hParent,
SADD ("Do you want to overwrite the current memory snapshot ?"),
SADD ("Confirm overwrite"),
MB_YESNO or MB_ICONQUESTION
.if eax == IDNO
ret
.endif
.endif
mov al, HardwareMode
mov SaveHardwareMode, al
memcpy addr Z80SYSTEMSTART, addr Z80SystemSnapshot, Z80SYSTEMSIZE
; copy Spectrum memory from first defined bank to the backup memory area
memcpy currentMachine.bank5, addr MemSnapshot, (16384*8)
; enable 'Load memory snapshot' and 'Cheats Finder' main window menu items
invoke EnableMenuItem, MenuHandle, IDM_LOADMEMSNAP, MF_BYCOMMAND or MF_ENABLED
mov MemorySnapshotValid, TRUE
ret
SaveMemorySnapshot endp
LoadMemorySnapshot proc hParent: HWND
.if MemorySnapshotValid
memcpy addr Z80SystemSnapshot, addr Z80SYSTEMSTART, Z80SYSTEMSIZE
mov al, SaveHardwareMode
mov HardwareMode, al ; restore hardware mode
memcpy addr MemSnapshot, currentMachine.bank5, (16384*8)
mov ax, zPC
mov Z80PC, ax
mov al, Last_FE_Write
call Set_BorderColour ; restore the border colour
invoke SetSnowEffect
invoke SetMachineStatusBar
.endif
ret
LoadMemorySnapshot endp
;############################################################################################
align 16
GetZ80MemoryAddr proc uses ecx,
address:WORD
movzx eax, address
mov ecx, eax
shr eax, 11
and eax, 28
mov eax, [currentMachine.RAMREAD0+eax]
and ecx, 1FFFh
add eax, ecx
ret
GetZ80MemoryAddr endp
align 16
ReadZ80Byte proc address:WORD
invoke GetZ80MemoryAddr, address
mov al, [eax]
ret
ReadZ80Byte endp
align 16
ReadZ80Word proc address:WORD
invoke GetZ80MemoryAddr, address
mov ax, [eax]
ret
ReadZ80Word endp
align 16
WriteZ80Byte proc uses ecx,
address:WORD,
data: BYTE
invoke GetZ80MemoryAddr, address
mov cl, data
mov [eax], cl
ret
WriteZ80Byte endp
align 16
WriteZ80Word proc uses ecx,
address:WORD,
data: WORD
invoke GetZ80MemoryAddr, address
mov cx, data
mov [eax], cx
ret
WriteZ80Word endp
align 16
GetBankAddr proc bank:BYTE
movzx eax, bank
and eax, 7
mov eax, [currentMachine.bank_ptrs+eax*4]
ret
GetBankAddr endp
align 16
ReadBankByte proc uses ecx,
bank: BYTE,
address:WORD
invoke GetBankAddr, bank
movzx ecx, address
and ecx, 3FFFh
mov al, [eax+ecx]
ret
ReadBankByte endp
align 16
ReadBankWord proc uses ecx,
bank: BYTE,
address:WORD
invoke GetBankAddr, bank
movzx ecx, address
and ecx, 3FFFh
mov ax, [eax+ecx]
ret
ReadBankWord endp
align 16
WriteBankByte proc uses ecx,
bank: BYTE,
address:WORD,
data: BYTE
invoke GetBankAddr, bank
movzx ecx, address
and ecx, 3FFFh
add eax, ecx
mov cl, data
mov [eax], cl
ret
WriteBankByte endp
align 16
WriteBankWord proc uses ecx,
bank: BYTE,
address:WORD,
data: WORD
invoke GetBankAddr, bank
movzx ecx, address
and ecx, 3FFFh
add eax, ecx
mov cx, data
mov [eax], cx
ret
WriteBankWord endp
;############################################################################################
align 16
; returns RAM page paged at specified address
; returns -1 if not RAM at that address
GetBankAtAddr proc uses ecx,
address:WORD
movzx ecx, address
shr ecx, 11 ; bits 15+14 >> bits 4+3
and ecx, 24 ; (0 - 3) * 8
mov ecx, [currentMachine.RAMREAD0+ecx] ; = RAMREAD0/2/4/6
xor eax, eax
@@: cmp ecx, [currentMachine.bank_ptrs+eax*4]
je @F
add eax, 1
cmp eax, 8
jc @B
or eax, -1
@@: ret
GetBankAtAddr endp
align 16
GetBankConfig proc uses ecx
invoke GetBankAtAddr, 0
and eax, 0Fh
shl ecx, 4
or ecx, eax
invoke GetBankAtAddr, 16384
and eax, 0Fh
shl ecx, 4
or ecx, eax
invoke GetBankAtAddr, 32768
and eax, 0Fh
shl ecx, 4
or ecx, eax
invoke GetBankAtAddr, 49152
and eax, 0Fh
shl ecx, 4
or ecx, eax
return ecx
GetBankConfig endp
GETRUNBYTE macro
push ebx
movzx ebx, Reg_PC
inc Reg_PC
inc Reg_InsLength
GETOPCODEBYTE
pop ebx
endm
;############################################################################################
; Force ULA contention delay for this cycle.
FORCECONTENTION macro
push edx
lea edx, ContentionTable
add edx, Reg_totaltstates
movzx edx, byte ptr [edx]
add Reg_totaltstates, edx
pop edx
endm
; Force ULA contention delays for an address.
FORCEMULTICONTENTION MACRO Repetitions:REQ
push edi
push ecx
lea edi, ContentionTable
mov ecx, Reg_totaltstates
REPEAT Repetitions
movzx ebx, byte ptr [edi+ecx]
lea ecx, [ecx+ebx+1] ; add contention + 1 cycle
ENDM
mov Reg_totaltstates, ecx
pop ecx
pop edi
ENDM
; Add ULA contention delay for an address.
; bx = address to apply contention to.
ADDCONTENTION macro
push ebx
shr ebx, 11
and ebx, 28
.if [currentMachine.CONTENTION0+ebx] == TRUE
mov ebx, Reg_totaltstates
movzx ebx, byte ptr [ContentionTable+ebx]
add Reg_totaltstates, ebx
.endif
pop ebx
endm
; Add ULA contention delays for an address.
; bx = address to apply contention to.
ADDMULTICONTENTION macro Repetitions
.if MACHINE.Plus3_Compatible
add Reg_totaltstates, Repetitions
.else
push eax
mov eax, Repetitions
call Add_Multi_Contention
pop eax
.endif
endm
ADD_IR_CYCLES macro Repetitions
mov bh, Reg_I
; mov bl, Reg_R ; R (and bl) don't affect IR contended cycles
ADDMULTICONTENTION Repetitions
endm
; Add ULA contention delays for the address in PC.
; - though we actually apply contention to PC-1 as we've incremented past an indexed offset byte
; - used in (IX/Y+dd) opcodes
ADDMULTICONTENTIONPC macro Repetitions
push ebx
movzx ebx, Reg_PC
dec ebx ; apply contention to PC-1 address
ADDMULTICONTENTION Repetitions
pop ebx
endm
align 16
; *****************************************************************
; turn on indirect addressing here
USEESI 1
; *****************************************************************
ExecZ80Opcode: lea esi, RegisterBase
ifc DoLogging then invoke Log_PC
inc Reg_opcodes_executed
xor eax, eax
movzx ebx, Reg_PC
; z80 states cleared to zero before executing an opcode
mov Reg_ClearZ80State1, eax
mov Reg_ClearZ80State2, eax
mov Reg_ClearZ80State3, eax
mov Reg_ClearZ80State4, eax
mov Reg_PrevzPC, bx
.if HardwareMode == HW_PENTAGON128
; TR-DOS maps in when PC = #3Dxx
.if (bh == 3Dh) || (bx == 3C00h) || (bx == 3C03h)
; only page in if unpaged and ROM 1 (48K ROM) is active
.if (TrDos_Paged == FALSE) && (currentMachine.RAMREAD0 == offset Rom_Pentagon128+16384) ; bit 4 of #7ffd = 1 ?
call TrDos_Page_In
.endif
; TR-DOS maps out when PC > #3FFF
.elseif ebx > 3FFFh
.if TrDos_Paged
call TrDos_Page_Out
.endif
.endif
.endif
.if (ebx <= 028Eh) && PLUSD_Enabled
.if (ebx == 8) || (ebx == 3Ah) || (ebx == 66h) || (ebx == 028Eh)
invoke PLUSD_PageIn
.endif
.endif
.if (ebx == 2BAEh) && MicroSourceEnabled ; 2BAE = 11182
xor MicroSourcePaged, TRUE
.if !ZERO?
mov currentMachine.RAMREAD0, offset Rom_MicroSource
mov currentMachine.RAMREAD1, offset Rom_MicroSource
.else
mov currentMachine.RAMREAD0, offset Rom_48
mov currentMachine.RAMREAD1, offset Rom_48+8192
.endif
.endif
FETCH_OPCODE offset Z80JumpTable
jmp ecx ; jump to opcode handler
; =================================================================
align 16
; eax = contended cycle repetitions
; bx = contention address
Add_Multi_Contention:; .if MACHINE.Plus3_Compatible ; +2A/+3 multi-contention now applied via macro before calling here
push ebx
shr ebx, 11
and ebx, 28
.if [currentMachine.CONTENTION0+ebx] == FALSE
pop ebx
add Reg_totaltstates, eax ; SETTS eax
ret
.endif
push ecx
mov ecx, Reg_totaltstates
push edi
lea edi, ContentionTable
@@: movzx ebx, byte ptr [edi+ecx]