~amaurycarvalho/msxbas2asm/trunk

« back to all changes in this revision

Viewing changes to test/stars.asm

  • Committer: Amaury Carvalho
  • Date: 2020-06-12 13:08:59 UTC
  • Revision ID: amauryspires@gmail.com-20200612130859-3qm5vl1jiqr2brok
Commit on 12/06/2020 10:08:59  -03 by amaury

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
;---------------------------------------------------------------------------------------------------------
2
 
; Source code converted by MSXBAS2ASM - MSX BASIC TO Z80 ASSEMBLY CONVERTER
3
 
; MSXBAS2ASM developed by Amaury Carvalho, 2019, Brazil
4
 
; http://launchpad.net/msxbas2asm
5
 
;---------------------------------------------------------------------------------------------------------
6
 
 
7
 
;--------------------------------------------------------
8
 
; MSX BIOS DATA/FUNCTION POINTERS
9
 
;--------------------------------------------------------
10
 
 
11
 
;---------------------------------------------------------------------------------------------------------
12
 
; BIOS FUNCTIONS
13
 
;---------------------------------------------------------------------------------------------------------
14
 
 
15
 
BIOS_CALBAS:    equ 0x0159
16
 
BIOS_OUTDO:     equ 0x0018   ; output to current device (i.e. screen)
17
 
BIOS_CHPUT:     equ 0x00A2
18
 
BIOS_CLS:       equ 0x00C3
19
 
BIOS_POSIT:     equ 0x00C6
20
 
BIOS_BEEP:      equ 0x00C0
21
 
BIOS_CHGET:     equ 0x009F
22
 
BIOS_CHSNS:     equ 0x009C
23
 
BIOS_INLIN:     equ 0x00B1
24
 
BIOS_PINLIN:    equ 0x00AE
25
 
BIOS_QINLIN:    equ 0x00B4
26
 
BIOS_GTSTCK:    equ 0x00D5
27
 
BIOS_GTTRIG:    equ 0x00D8
28
 
BIOS_GTPAD:     equ 0x00DB
29
 
BIOS_GTPDL:     equ 0x00DE
30
 
BIOS_DISSCR:    equ 0x0041
31
 
BIOS_ENASCR:    equ 0x0044
32
 
BIOS_CHGMOD:    equ 0x005F
33
 
BIOS_CHGCLR:    equ 0x0062
34
 
BIOS_CLRSPR:    equ 0x0069
35
 
BIOS_INITXT:    equ 0x006C    ; init text mode 40 columns
36
 
BIOS_INIT32:    equ 0x006F    ; init text mode 32 columns
37
 
BIOS_INIGRP:    equ 0x0072
38
 
BIOS_INIMLT:    equ 0x0075
39
 
BIOS_SETTXT:    equ 0x0078    ; set text mode 40 columns
40
 
BIOS_SETT32:    equ 0x007B    ; set text mode 32 columns
41
 
BIOS_SETGRP:    equ 0x007E
42
 
BIOS_SETMLT:    equ 0x0081
43
 
BIOS_CALPAT:    equ 0x0084
44
 
BIOS_CALATR:    equ 0x0087
45
 
BIOS_GSPSIZ:    equ 0x008A
46
 
BIOS_GRPPRT:    equ 0x008D
47
 
BIOS_ERAFNK:    equ 0x00CC
48
 
BIOS_DSPFNK:    equ 0x00CF
49
 
BIOS_TOTEXT:    equ 0x00D2
50
 
BIOS_BREAKX:    equ 0x00B7
51
 
BIOS_ISCNTC:    equ 0x03FB
52
 
BIOS_CHKRAM:    equ 0x0000
53
 
BIOS_GICINI:    equ 0x0090
54
 
BIOS_WRTPSG:    equ 0x0093
55
 
BIOS_REDPSG:    equ 0x0096
56
 
BIOS_STRTMS:    equ 0x0099
57
 
BIOS_KEYINT:    equ 0x0038
58
 
BIOS_CALSLT:    equ 0x001C
59
 
BIOS_ENASLT:    equ 0x0024
60
 
BIOS_RSLREG:    equ 0x0138
61
 
BIOS_SCALXY:    equ 0x010E
62
 
BIOS_MAPXYC:    equ 0x0111      ; in BC = X, DE = Y
63
 
BIOS_READC:     equ 0x011D      ; out A = color of current pixel
64
 
BIOS_SETATR:    equ 0x011A      ; in A = color code
65
 
BIOS_SETC:      equ 0x0120      ; set current pixel to color from SETATR
66
 
BIOS_NSETCX:    equ 0x0123      ; in HL = pixel fill count
67
 
BIOS_SCANR:     equ 0x012C      ; in B=Fill switch, DE=Skip count, out DE=Skip remainder, HL=Pixel count
68
 
BIOS_SCANL:     equ 0x012F      ; out HL=Pixel count
69
 
BIOS_FETCHC:    equ 0x0114      ; out A = cursor mask, HL = VRAM address of cursor
70
 
BIOS_STOREC:    equ 0x0117      ; in A = cursor mask, HL = VRAM address of cursor
71
 
BIOS_RESET:     equ 0x7D17      ; restart BASIC
72
 
BIOS_IOALLOC:   equ 0X7e6b      ; memory setup
73
 
 
74
 
BIOS_GETVCP:    equ 0x0150      ; get PSG voice buffer address (in A = voice number, out HL = address of byte 2)
75
 
BIOS_GETVC2:    equ 0x0153      ; get PSG voice buffer address (VOICEN = voice number, in L = byte number 0-36, out HL = address)
76
 
 
77
 
BIOS_CHPUT_LF:  equ 0x0908
78
 
BIOS_CHPUT_CR:  equ 0x0A81
79
 
BIOS_CHPUT_TAB: equ 0x0A71
80
 
 
81
 
; MSX2
82
 
BIOS_CHKNEW:    equ 0x0165      ; C-flag set if screenmode = 5, 6, 7 or 8
83
 
BIOS_EXTROM:    equ     0x015F
84
 
BIOS_SCALXY2:   equ 0x008D      ; in BC = X, DE = Y
85
 
BIOS_MAPXYC2:   equ 0x0091      ; in BC = X, DE = Y
86
 
BIOS_SETC2:     equ 0x009D      ; set current pixel to color from SETATR
87
 
BIOS_READC2:    equ 0x0095      ; out A = color of current pixel
88
 
BIOS_CHGMOD2:   equ 0x00D1      ; in A = screenmode
89
 
BIOS_DOBOXF:    equ 0x0079      ; hl = basic text pointer
90
 
BIOS_GRPPRT2:   equ 0x0089      ; a = character
91
 
BIOS_CHGCLR2:   equ 0x0111      ; change color, a = screen mode
92
 
BIOS_CALPAT2:   equ 0x00F9
93
 
BIOS_CALATR2:   equ 0x00FD
94
 
BIOS_GSPSIZ2:   equ 0x0101
95
 
BIOS_CLRSPR2:   equ 0x00F5
96
 
 
97
 
;---------------------------------------------------------------------------------------------------------
98
 
; BIOS WORK AREAS
99
 
;---------------------------------------------------------------------------------------------------------
100
 
 
101
 
BIOS_VERSION:   equ 0x002D   ; 0 = MSX1, 1 = MSX2, 2 = MSX2+, 3 = MSXturboR
102
 
BIOS_FORCLR:    equ 0xF3E9
103
 
BIOS_BAKCLR:    equ 0xF3EA
104
 
BIOS_BDRCLR:    equ 0xF3EB
105
 
BIOS_ATRBYT:    equ 0xF3F2
106
 
BIOS_INTFLG:    equ 0xFC9B
107
 
BIOS_EXPTBL:    equ 0xFCC1
108
 
BIOS_JIFFY:     equ 0xFC9E
109
 
BIOS_BOTTOM:    equ 0xFC48
110
 
BIOS_HIMEM:     equ 0xFC4A
111
 
BIOS_SCRMOD:    equ 0xFCAF   ; 0=40x24 Text Mode, 1=32x24 Text Mode, 2=Graphics Mode, 3=Multicolour Mode.
112
 
BIOS_CLIKSW:    equ 0xF3DB   ; 0=keyboard click off, 1=keyboard click on
113
 
BIOS_GRPACX:    equ 0xFCB7
114
 
BIOS_GRPACY:    equ 0xFCB9
115
 
BIOS_DATLIN:    equ 0xF6A3   ; 2 - line number of DATA statement read by READ statement
116
 
BIOS_DATPTR:    equ 0xF6C8   ; 2 - address of data read by executing READ statement
117
 
BIOS_FLGINP:    equ 0xF6A6   ; 1 - flag used in INPUT or READ
118
 
BIOS_TEMP:      equ 0xF6A7   ; 2
119
 
BIOS_TEMP2:     equ 0xF6BC   ; 2
120
 
BIOS_TEMP3:     equ 0xF69D   ; 2
121
 
BIOS_TEMP8:     equ 0xF69F   ; 2
122
 
BIOS_TEMP9:     equ 0xF7B8   ; 2
123
 
BIOS_OLDSCR:    equ 0xFCB0   ; screen mode of the last text mode set
124
 
BIOS_LINL40:    equ 0xF3AE   ; width for 40 columns screen mode
125
 
BIOS_LINL32:    equ 0xF3AF   ; width for 32 columns screen mode
126
 
BIOS_LINLEN:    equ 0xF3B0   ; current width for text screen mode
127
 
BIOS_CLMLST:    equ 0xF3B2   ; minimum number of columns that must still be available on a line for a CRLF
128
 
BIOS_TXTNAM:    equ 0xF3B3   ; characters table name
129
 
 
130
 
BIOS_VOICEN:    equ 0xFB38   ; PSG voice number
131
 
BIOS_MCLTAB:    equ 0xF956
132
 
BIOS_PRSCNT:    equ 0xFB35
133
 
BIOS_SAVSP:     equ 0xFB36
134
 
BIOS_QUEUEN:    equ 0xFB3E
135
 
BIOS_MUSICF:    equ 0xFB3F   ;contains 3 bit flags set by the STRTMS. Bits 0, 1 and 2 correspond to VOICAQ, VOICBQ and VOICCQ.
136
 
BIOS_PLYCNT:    equ 0xFB40
137
 
 
138
 
BIOS_DRWFLG:    equ 0xFCBB
139
 
BIOS_MCLFLG:    equ 0xF958
140
 
 
141
 
BIOS_SLTROM:    equ 0xFCC1
142
 
BIOS_RAMAD0:    equ     0xF341  ; Main-RAM Slot (00000h~03FFFh)
143
 
BIOS_RAMAD1:    equ     0xF342  ; Main-RAM Slot (04000h~07FFFh)
144
 
BIOS_RAMAD2:    equ     0xF343  ; Main-RAM Slot (08000h~0BFFFh)
145
 
BIOS_RAMAD3:    equ     0xF344  ; Main-RAM Slot (0C000h~0FFFFh)
146
 
 
147
 
 
148
 
 
149
 
;--------------------------------------------------------
150
 
; MSX BASIC DATA/FUNCTION POINTERS
151
 
;--------------------------------------------------------
152
 
 
153
 
;---------------------------------------------------------------------------------------------------------
154
 
; MSX BASIC FUNCTIONS
155
 
;---------------------------------------------------------------------------------------------------------
156
 
 
157
 
BASIC_AUTO:   equ 0x3973
158
 
BASIC_AND:    equ 0x3A18
159
 
BASIC_ATTR:   equ 0x39FE
160
 
BASIC_BASE:   equ 0x39BE
161
 
BASIC_BSAVE:  equ 0x39CC
162
 
BASIC_BLOAD:  equ 0x39CA
163
 
BASIC_BEEP:   equ 0x39AC
164
 
BASIC_CALL:   equ 0x39C0
165
 
BASIC_CLOSE:  equ 0x3994
166
 
BASIC_COPY:   equ 0x39D8
167
 
BASIC_CONT:   equ 0x395E
168
 
BASIC_CLEAR:  equ 0x3950
169
 
BASIC_CLOAD:  equ 0x3962
170
 
BASIC_CSAVE:  equ 0x3960
171
 
BASIC_CSRLIN: equ 0x39FC
172
 
BASIC_CIRCLE: equ 0x39A4
173
 
BASIC_COLOR:  equ 0x39A6
174
 
BASIC_CLS:    equ 0x396A
175
 
BASIC_CMD:    equ 0x39DA
176
 
BASIC_DELETE: equ 0x397C
177
 
BASIC_DATA:   equ 0x3934
178
 
BASIC_DIM:    equ 0x3938
179
 
BASIC_DEFSTR: equ 0x3982
180
 
BASIC_DEFINT: equ 0x3984
181
 
BASIC_DEFSNG: equ 0x3986
182
 
BASIC_DEFDBL: equ 0x3988
183
 
BASIC_DSKO:   equ 0x39CE
184
 
BASIC_DEF:    equ 0x395A
185
 
BASIC_DSKI:   equ 0x3A00
186
 
BASIC_DRAW:   equ 0x39A8
187
 
BASIC_ELSE:   equ 0x396E
188
 
BASIC_END:    equ 0x392E
189
 
BASIC_ERASE:  equ 0x3976
190
 
BASIC_ERROR:  equ 0x3978
191
 
BASIC_ERL:    equ 0x39EE
192
 
BASIC_ERR:    equ 0x39F0
193
 
BASIC_EQU:    equ 0x3A1E
194
 
BASIC_FOR:    equ 0x3920
195
 
BASIC_FIELD:  equ 0x398E
196
 
BASIC_FILES:  equ 0x39AA
197
 
BASIC_FN:     equ 0x39E8
198
 
BASIC_GOTO:   equ 0x393E
199
 
BASIC_GOSUB:  equ 0x3948
200
 
BASIC_GET:    equ 0x3990
201
 
BASIC_INPUT:  equ 0x3936
202
 
BASIC_IF:     equ 0x3942
203
 
BASIC_INSTR:  equ 0x39F6
204
 
BASIC_IMP:    equ 0x3A20
205
 
BASIC_INKEY:  equ 0x3A04
206
 
BASIC_IPL:    equ 0x39D6
207
 
BASIC_KILL:   equ 0x39D4
208
 
BASIC_KEY:    equ 0x3964
209
 
BASIC_LPRINT: equ 0x394C
210
 
BASIC_LLIST:  equ 0x3968
211
 
BASIC_LET:    equ 0x393C
212
 
BASIC_LOCATE: equ 0x39DC
213
 
BASIC_LINE:   equ 0x398A
214
 
BASIC_LOAD:   equ 0x3996
215
 
BASIC_LSET:   equ 0x399C
216
 
BASIC_LIST:   equ 0x3952
217
 
BASIC_LFILES: equ 0x39A2
218
 
BASIC_MOTOR:  equ 0x39C8
219
 
BASIC_MERGE:  equ 0x3998
220
 
BASIC_MOD:    equ 0x3A22
221
 
BASIC_MAX:    equ 0x39C6
222
 
BASIC_NEXT:   equ 0x3932
223
 
BASIC_NAME:   equ 0x39D2
224
 
BASIC_NEW:    equ 0x3954
225
 
BASIC_NOT:    equ 0x39EC
226
 
BASIC_OPEN:   equ 0x398C
227
 
BASIC_OUT:    equ 0x3964
228
 
BASIC_ON:     equ 0x3956
229
 
BASIC_OR:     equ 0x3A1A
230
 
BASIC_OFF:    equ 0x3A02
231
 
BASIC_PRINT:  equ 0x394E
232
 
BASIC_PUT:    equ 0x3992
233
 
BASIC_POKE:   equ 0x395C
234
 
BASIC_PSET:   equ 0x39B0
235
 
BASIC_PRESET: equ 0x39B2
236
 
BASIC_POINT:  equ 0x3A06
237
 
BASIC_PAINT:  equ 0x39AA
238
 
BASIC_PLAY:   equ 0x39AE
239
 
BASIC_RETURN: equ 0x3948
240
 
BASIC_READ:   equ 0x393A
241
 
BASIC_RUN:    equ 0x3940
242
 
BASIC_RESTORE:equ 0x3944
243
 
BASIC_REM:    equ 0x394A
244
 
BASIC_RESUME: equ 0x397A
245
 
BASIC_RSET:   equ 0x399E
246
 
BASIC_RENUM:  equ 0x3980
247
 
BASIC_SCREEN: equ 0x39B6
248
 
BASIC_SPRITE: equ 0x39BA
249
 
BASIC_STOP:   equ 0x394C
250
 
BASIC_SWAP:   equ 0x3974
251
 
BASIC_SET:    equ 0x39D0
252
 
BASIC_SAVE:   equ 0x39A0
253
 
BASIC_SPC:    equ 0x39EA
254
 
BASIC_STEP:   equ 0x39E4
255
 
BASIC_STRING: equ 0x39F2
256
 
BASIC_SPACE1: equ 0x397E
257
 
BASIC_SOUND:  equ 0x39B4
258
 
BASIC_THEN:   equ 0x39E0
259
 
BASIC_TRON:   equ 0x3970
260
 
BASIC_TROFF:  equ 0x3972
261
 
BASIC_TAB:    equ 0x39E2
262
 
BASIC_TO:     equ 0x39DE
263
 
BASIC_TIME:   equ 0x39C2
264
 
BASIC_USING:  equ 0x39F4
265
 
BASIC_USR:    equ 0x39E6
266
 
BASIC_VARPTR: equ 0x39FA
267
 
BASIC_VDP:    equ 0x39BC
268
 
BASIC_VPOKE:  equ 0x39B8
269
 
BASIC_WIDTH:  equ 0x396C
270
 
BASIC_WAIT:   equ 0x3958
271
 
BASIC_XOR:    equ 0x3A1C
272
 
BASIC_ABS:    equ 0x39E8
273
 
BASIC_ATN:    equ 0x39F8
274
 
BASIC_ASC:    equ 0x3A06
275
 
BASIC_BIN:    equ 0x3A16
276
 
BASIC_CINT:   equ 0x3A18
277
 
BASIC_CSNG:   equ 0x3A1A
278
 
BASIC_CDBL:   equ 0x3A1C
279
 
BASIC_CVI:    equ 0x3A2C
280
 
BASIC_CVS:    equ 0x3A2E
281
 
BASIC_CVD:    equ 0x3A30
282
 
BASIC_COS:    equ 0x39F4
283
 
BASIC_CHR:    equ 0x3A08
284
 
BASIC_DSKF:   equ 0x3A28
285
 
BASIC_EXP:    equ 0x39F2
286
 
BASIC_EOF:    equ 0x3A32
287
 
BASIC_FRE:    equ 0x39FA
288
 
BASIC_FIX:    equ 0x3A1E
289
 
BASIC_FPOS:   equ 0x3A2A
290
 
BASIC_HEX:    equ 0x3A12
291
 
BASIC_INT:    equ 0x39E6
292
 
BASIC_INP:    equ 0x39FC
293
 
BASIC_LPOS:   equ 0x3A14
294
 
BASIC_LOG:    equ 0x39F0
295
 
BASIC_LOC:    equ 0x3A34
296
 
BASIC_LEN:    equ 0x3A00
297
 
BASIC_LEFT:   equ 0x39DE
298
 
BASIC_LOF:    equ 0x3A36
299
 
BASIC_MKI:    equ 0x3A38
300
 
BASIC_MKS:    equ 0x3A3A
301
 
BASIC_MKD:    equ 0x3A3C
302
 
BASIC_MID:    equ 0x39E2
303
 
BASIC_OCT:    equ 0x3A10
304
 
BASIC_POS:    equ 0x39FE
305
 
BASIC_PEEK:   equ 0x3A0A
306
 
BASIC_PDL:    equ 0x3A24
307
 
BASIC_PAD:    equ 0x3A26
308
 
BASIC_RIGHT:  equ 0x39E0
309
 
BASIC_RND:    equ 0x39EC
310
 
BASIC_SGN:    equ 0x39E4
311
 
BASIC_SQR:    equ 0x39EA
312
 
BASIC_SIN:    equ 0x39EE
313
 
BASIC_STR:    equ 0x3A02
314
 
BASIC_SPACE2: equ 0x3A0E
315
 
BASIC_STICK:  equ 0x3A20
316
 
BASIC_STRIG:  equ 0x3A22
317
 
BASIC_TAN:    equ 0x39F6
318
 
BASIC_VAL:    equ 0x3A04
319
 
BASIC_VPEEK:  equ 0x3A0C
320
 
 
321
 
BASIC_TRAP_ENABLE:  equ 0x631B    ; ON INTERVAL/KEY/SPRITE/STOP/STRIG - hl = pointer to trap block
322
 
BASIC_TRAP_DISABLE: equ 0x632B    ; hl = pointer to trap block
323
 
BASIC_TRAP_ACKNW:   equ 0x6358    ; hl, acknowledge trap (handle trap: sts=5? has handler? ackn, pause, run trap, sts=1? unpause)
324
 
BASIC_TRAP_PAUSE:   equ 0x6331    ; hl
325
 
BASIC_TRAP_UNPAUSE: equ 0x633E    ; hl
326
 
BASIC_TRAP_CLEAR:   equ 0x636E
327
 
 
328
 
BASIC_PLAY_DIRECT:  equ 0x744C
329
 
BASIC_DRAW_DIRECT:  equ 0x568C
330
 
 
331
 
BASIC_READYR:       equ 0x409B
332
 
BASIC_READYC:       equ 0x7D17
333
 
BASIC_FACEVAL:      equ 0x4DC7
334
 
 
335
 
BASIC_ERROR_HANDLER:equ 0x406F
336
 
BASIC_ERROR_SYNTAX: equ 0x4055
337
 
BASIC_ERROR_DIVZER: equ 0x4058
338
 
BASIC_ERROR_OVRFLW: equ 0x4067
339
 
BASIC_ERROR_ARRAY:  equ 0x405E
340
 
BASIC_ERROR_TYPMIS: equ 0x406D
341
 
 
342
 
; BASIC ERROR CODES TO BASIC_ERROR_HANDLER
343
 
; 01 NEXT without FOR             19 Device I/O error
344
 
; 02 Syntax error                 20 Verify error
345
 
; 03 RETURN without GOSUB         21 No RESUME
346
 
; 04 Out of DATA                  22 RESUME without error
347
 
; 05 Illegal function call        23 Unprintable error
348
 
; 06 Overflow                     24 Missing operand
349
 
; 07 Out of memory                25 Line buffer overflow
350
 
; 08 Undefined line number        50 FIELD overflow
351
 
; 09 Subscript out of range       51 Internal error
352
 
; 10 Redimensioned array          52 Bad file number
353
 
; 11 Division by zero             53 File not found
354
 
; 12 Illegal direct               54 File already open
355
 
; 13 Type mismatch                55 Input past end
356
 
; 14 Out of string space          56 Bad file name
357
 
; 15 String too long              57 Direct statement in file
358
 
; 16 String formula too complex   58 Sequential I/O only
359
 
; 17 Can't CONTINUE               59 File not OPEN
360
 
; 18 Undefined user function
361
 
 
362
 
;---------------------------------------------------------------------------------------------------------
363
 
; MSX BASIC WORK AREAS
364
 
;---------------------------------------------------------------------------------------------------------
365
 
 
366
 
BASIC_DAC:    equ 0xF7F6    ; 16
367
 
BASIC_ARG:    equ 0xF847    ; 16
368
 
BASIC_VALTYP: equ 0xF663
369
 
BASIC_RNDX:   equ 0xF857
370
 
BASIC_BUF:    equ 0xF55E    ; 259
371
 
BASIC_KBUF:   equ 0xF41F    ; 318
372
 
BASIC_SWPTMP: equ 0xF7BC    ; 8
373
 
BASIC_STRBUF: equ 0xF7C5    ; 43
374
 
BASIC_TXTTAB: equ 0xF676
375
 
BASIC_VARTAB: equ 0xF6C2
376
 
BASIC_ARYTAB: equ 0xF6C4
377
 
BASIC_STREND: equ 0xF6C6
378
 
BASIC_STKTOP: equ 0xF674
379
 
BASIC_FRETOP: equ 0xF69B
380
 
BASIC_MEMSIZ: equ 0xF672
381
 
 
382
 
BASIC_TEMPPT: equ 0xF678    ; 2 Starting address of unused area of temporary descriptor.
383
 
BASIC_TEMPST: equ 0xF67A    ; 30 Temporary descriptors.
384
 
 
385
 
BASIC_DATPTR: equ 0xF6C8    ; 2 Pointer to next data to read from the instruction DATA. Modified by RESTORE.
386
 
BASIC_DATLIN: equ 0xF6A3    ; 2 Número de linha do comando DATA para o comando READ.
387
 
BASIC_DORES:  equ 0xF664    ; 1 Usada pelo comando DATA para manter o texto no formato ASCII.
388
 
BASIC_DEFTBL: equ 0xF6CA    ; 26 table of variables defined by DEFINT, DEFSTR, DEFSNG and DEFDBL for each alphabet letter (2 = integer, 3 = String, 4 = Simple precision, 8 = Double precision).
389
 
 
390
 
BASIC_CURLIN: equ 0xF41C    ; BASIC current line number
391
 
BASIC_INTVAL: equ 0xFCA0    ; interval value
392
 
BASIC_INTCNT: equ 0xFCA2    ; interval current count
393
 
 
394
 
BASIC_PRMPRV: equ 0xF74C    ; Pointer to previous parameter block in PARM1
395
 
 
396
 
BASIC_TRPTBL: equ 0xFC4C    ; 78 trap table - array of 3 bytes - state[1] (bit 0=on, bit 1=stop, bit 2=active) + address[2]
397
 
 
398
 
BASIC_TRPTBL_KEY:        equ 0xFC4C  ; 30 ON KEY GOSUB
399
 
BASIC_TRPTBL_STOP:       equ 0xFC6A  ; 3  ON STOP GOSUB
400
 
BASIC_TRPTBL_SPRITE:     equ 0xFC6D  ; 3  ON SPRITE GOSUB
401
 
BASIC_TRPTBL_STRIG:      equ 0xFC70  ; 15 ON STRIG GOSUB
402
 
BASIC_TRPTBL_INTERVAL:   equ 0xFC7F  ; 3  ON INTERVAL GOSUB
403
 
BASIC_TRPTBL_OTHER:      equ 0xFC82  ; 24 reserved for expansion
404
 
 
405
 
BASIC_ONGSBF:            equ 0xFBD8  ; 1  trap occurred counter (0=not occurred)
406
 
 
407
 
 
408
 
 
409
 
;--------------------------------------------------------
410
 
; MATH PACK ROUTINES
411
 
;--------------------------------------------------------
412
 
 
413
 
;--------------------------------------------------------
414
 
; SUPPORT MACROS
415
 
;--------------------------------------------------------
416
 
COMPILE_TO_ROM: EQU 1
417
 
 
418
 
MACRO __call_basic,CALL_PARM
419
 
    ld ix, CALL_PARM
420
 
    call BIOS_CALBAS
421
 
ENDM
422
 
 
423
 
if defined COMPILE_TO_DOS
424
 
 
425
 
  MACRO __call_bios,CALL_PARM
426
 
    ;ld iy,(BIOS_EXPTBL-1)
427
 
    ld ix, CALL_PARM
428
 
    call BIOS_CALBAS   ; BIOS_CALSLT
429
 
  ENDM
430
 
 
431
 
else
432
 
 
433
 
  MACRO __call_bios,CALL_PARM
434
 
    call CALL_PARM
435
 
  ENDM
436
 
 
437
 
endif
438
 
 
439
 
MACRO push.parm
440
 
    push hl ; save parameter
441
 
ENDM
442
 
 
443
 
MACRO pop.parm
444
 
    pop iy  ; restore PC of caller
445
 
    pop hl  ; get next parameter
446
 
    push iy ; save PC of caller
447
 
ENDM
448
 
 
449
 
MACRO push.ret.parm
450
 
    pop iy  ; restore PC of caller
451
 
    push hl ; save return parameter
452
 
    push iy ; save PC of caller
453
 
ENDM
454
 
 
455
 
MACRO ret.parm
456
 
    pop iy         ; restore PC of caller
457
 
    push hl        ; save return parameter
458
 
    push iy        ; save PC of caller
459
 
    ret            ; return
460
 
ENDM
461
 
 
462
 
MACRO set.line.number, line_number
463
 
    ld bc, line_number          ; current line number
464
 
    ld (BASIC_CURLIN), bc
465
 
ENDM
466
 
 
467
 
MACRO verify.break
468
 
    ld a, (BIOS_INTFLG)         ; verify CTRL+BREAK
469
 
    or a
470
 
    jp nz, end_pgm
471
 
ENDM
472
 
 
473
 
MACRO check.traps
474
 
     ld a, (BASIC_ONGSBF)       ; trap occured counter
475
 
     or a
476
 
     call nz, RUN_TRAPS
477
 
ENDM
478
 
 
479
 
 
480
 
;---------------------------------------------------------------------------------------------------------
481
 
; PROGRAM HEADER
482
 
;---------------------------------------------------------------------------------------------------------
483
 
 
484
 
    romSize:       equ  0x8000                 ; ROM size (32k)
485
 
    pageSize:      equ  0x4000                 ; Page size (16k)
486
 
    lowLimitSize:  equ  0x400                  ; 10% of a page size
487
 
 
488
 
if defined COMPILE_TO_BIN
489
 
 
490
 
    pgmArea:    equ  0x8000                 ; page 2 - program area
491
 
    ramArea:    equ  0xc000                 ; page 3 - free RAM start area
492
 
 
493
 
    org  pgmArea                ; program binary type start address
494
 
    db   0FEh                       ; binary file ID
495
 
    dw   start_pgm                  ; begin address
496
 
    dw   end_file - 1           ; end address
497
 
    dw   start_pgm                  ; program execution address (for ,R option)
498
 
 
499
 
else
500
 
if defined COMPILE_TO_ROM
501
 
 
502
 
    pgmArea:    equ  0x4000                 ; page 1 and 2 - program area
503
 
    ramArea:    equ  0xc000                 ; page 3 - free RAM start area
504
 
 
505
 
    org  pgmArea                ; program rom type start address
506
 
    db   'AB'                   ; rom file ID
507
 
    dw   start_pgm              ; INIT
508
 
    dw   0x0000                 ; STATEMENT
509
 
    dw   0x0000                 ; DEVICE
510
 
    dw   0x0000                 ; TEXT
511
 
    ds   6,0                    ; RESERVED
512
 
 
513
 
else
514
 
 
515
 
    pgmArea:    equ  0x8000                 ; page 2 - program area
516
 
    ramArea:    equ  0xc000                 ; page 3 - free RAM start area
517
 
 
518
 
    org  pgmArea                ; program DOS type start address    ; 0x0100
519
 
 
520
 
endif
521
 
endif
522
 
 
523
 
 
524
 
;---------------------------------------------------------------------------------------------------------
525
 
; PROGRAM ROUTINES
526
 
;---------------------------------------------------------------------------------------------------------
527
 
 
528
 
if defined COMPILE_TO_ROM
529
 
 
530
 
PROGRAM_TO_BASIC:
531
 
    call PROGRAM_SLOT_2_RESTORE
532
 
    __call_basic BASIC_READYR    ; warm start Basic
533
 
    ret
534
 
 
535
 
PROGRAM_SLOT_2_SAVE:
536
 
    ld h,080h
537
 
    call PROGRAM_SLOT_GET
538
 
    ld (BIOS_RAMAD2), a ; Save RAM slot of page 8000h-BFFFh
539
 
    ret
540
 
 
541
 
PROGRAM_SLOT_2_RESTORE:
542
 
    ld a, (BIOS_RAMAD2)
543
 
        ld h,080h
544
 
        jp BIOS_ENASLT      ; Select the RAM on page 8000h-BFFFh
545
 
 
546
 
PROGRAM_SLOT_2_ENABLE:
547
 
    call BIOS_RSLREG
548
 
    call PROGRAM_SLOT_ENABLE_SUB
549
 
        ld      h,080h
550
 
        jp BIOS_ENASLT          ; Select the ROM on page 8000h-BFFFh
551
 
 
552
 
PROGRAM_SLOT_1_ENABLE:
553
 
    call BIOS_RSLREG
554
 
        rrca
555
 
        rrca
556
 
    call PROGRAM_SLOT_ENABLE_SUB
557
 
        ld      h,040h
558
 
        jp BIOS_ENASLT  ; Select the ROM on page 4000h-7FFFh
559
 
 
560
 
PROGRAM_SLOT_ENABLE_SUB:
561
 
        rrca
562
 
        rrca
563
 
        and     3       ;Keep bits corresponding to the page
564
 
        ld      c,a
565
 
        ld      b,0
566
 
        ld      hl,BIOS_EXPTBL
567
 
        add     hl,bc
568
 
        ld      a,(hl)
569
 
        and     80h
570
 
        or      c
571
 
        ld      c,a
572
 
        inc     hl
573
 
        inc     hl
574
 
        inc     hl
575
 
        inc     hl
576
 
        ld      a,(hl)
577
 
        and     0Ch
578
 
        or      c
579
 
    ret
580
 
 
581
 
; h = memory page
582
 
; a <- slot ID formatted FxxxSSPP
583
 
; Modifies: af, bc, de, hl
584
 
; ref: https://www.msx.org/forum/msx-talk/development/fusion-c-and-htimi#comment-366469
585
 
PROGRAM_SLOT_GET:
586
 
        call BIOS_RSLREG
587
 
        bit 7,h
588
 
        jr z,PrimaryShiftContinue
589
 
        rrca
590
 
        rrca
591
 
        rrca
592
 
        rrca
593
 
PrimaryShiftContinue:
594
 
        bit 6,h
595
 
        jr z,PrimaryShiftDone
596
 
        rrca
597
 
        rrca
598
 
PrimaryShiftDone:
599
 
        and 00000011B
600
 
        ld c,a
601
 
        ld b,0
602
 
        ex de,hl
603
 
        ld hl,BIOS_EXPTBL
604
 
        add hl,bc
605
 
        ld c,a
606
 
        ld a,(hl)
607
 
        and 80H
608
 
        or c
609
 
        ld c,a
610
 
        inc hl  ; move to SLTTBL
611
 
        inc hl
612
 
        inc hl
613
 
        inc hl
614
 
        ld a,(hl)
615
 
        ex de,hl
616
 
        bit 7,h
617
 
        jr z,SecondaryShiftContinue
618
 
        rrca
619
 
        rrca
620
 
        rrca
621
 
        rrca
622
 
SecondaryShiftContinue:
623
 
        bit 6,h
624
 
        jr nz,SecondaryShiftDone
625
 
        rlca
626
 
        rlca
627
 
SecondaryShiftDone:
628
 
        and 00001100B
629
 
        or c
630
 
        ret
631
 
 
632
 
endif
633
 
 
634
 
if defined COMPILE_TO_DOS
635
 
 
636
 
BIOS_SLOT_ENABLE:
637
 
               ld a, (BIOS_EXPTBL)
638
 
               ld hl,0
639
 
               __call_bios BIOS_ENASLT ; Select main ROM on page 0 (0000h~3FFFh)
640
 
               ret
641
 
 
642
 
BASIC_SLOT_ENABLE:
643
 
               ld a, (BIOS_EXPTBL)
644
 
               ld hl,04000h
645
 
               __call_bios BIOS_ENASLT ; Select main ROM on page 1 (4000h~7FFFh)
646
 
               ret
647
 
 
648
 
endif
649
 
 
650
 
 
651
 
 
652
 
;---------------------------------------------------------------------------------------------------------
653
 
; PROGRAM MAIN CODE
654
 
;---------------------------------------------------------------------------------------------------------
655
 
 
656
 
start_pgm:                               ; start of the program
657
 
 
658
 
    if defined COMPILE_TO_DOS
659
 
 
660
 
       call BIOS_SLOT_ENABLE   ; enable bios on page 0
661
 
       call BASIC_SLOT_ENABLE  ; enable basic on page 1
662
 
 
663
 
    else
664
 
       if defined COMPILE_TO_ROM
665
 
 
666
 
          call PROGRAM_SLOT_2_SAVE     ; save slot on page 2
667
 
          call PROGRAM_SLOT_2_ENABLE   ; enable program on page 2
668
 
 
669
 
       endif
670
 
    endif
671
 
 
672
 
    __call_bios BIOS_ERAFNK      ; turn off function keys display
673
 
    __call_bios BIOS_GICINI      ; initialize sound system
674
 
    __call_bios BIOS_INITXT      ; initialize text screen
675
 
    xor a
676
 
    ld (BIOS_CLIKSW), a          ; disable keyboard click
677
 
    ld bc, 0xFFFF                ;
678
 
    ld (BASIC_CURLIN), bc        ; interpreter in direct mode
679
 
    __call_basic BASIC_TRAP_CLEAR        ; clear traps work space
680
 
    ;call INITIALIZE_PARAMETERS   ; initialize parameters stack
681
 
    call memory.init             ; initialize memory allocation
682
 
    call INITIALIZE_VARIABLES    ; initialize variables
683
 
 
684
 
 
685
 
TAG_10:
686
 
            set.line.number     10      ; current line number
687
 
 
688
 
TAG_20:
689
 
            set.line.number     20      ; current line number
690
 
            ld hl, LIT_4                ; parameter
691
 
            push.parm
692
 
            call SCREEN                 ; action call
693
 
 
694
 
TAG_25:
695
 
            set.line.number     25      ; current line number
696
 
            ld hl, LIT_10               ; parameter
697
 
            push.parm
698
 
            ld hl, LIT_9                ; parameter
699
 
            push.parm
700
 
            ld hl, LIT_8                ; parameter
701
 
            push.parm
702
 
            ld hl, LIT_7                ; parameter
703
 
            push.parm
704
 
            call PSET.XY                ; action call
705
 
            call BOX                    ; action call
706
 
            ld hl, LIT_14               ; parameter
707
 
            push.parm
708
 
            ld hl, LIT_13               ; parameter
709
 
            push.parm
710
 
            ld hl, LIT_12               ; parameter
711
 
            push.parm
712
 
            ld hl, LIT_11               ; parameter
713
 
            push.parm
714
 
            call PSET.XY                ; action call
715
 
            call BOX                    ; action call
716
 
            ld hl, LIT_18               ; parameter
717
 
            push.parm
718
 
            ld hl, LIT_17               ; parameter
719
 
            push.parm
720
 
            ld hl, LIT_16               ; parameter
721
 
            push.parm
722
 
            ld hl, LIT_15               ; parameter
723
 
            push.parm
724
 
            call PSET.XY                ; action call
725
 
            call BOX                    ; action call
726
 
 
727
 
TAG_30:
728
 
            set.line.number     30      ; current line number
729
 
            ld hl, LIT_21               ; parameter
730
 
            push.parm
731
 
            ld hl, LIT_23               ; parameter
732
 
            push.parm
733
 
            call ATN                    ; action call
734
 
            call MATH.MULT              ; action call
735
 
            ld hl, IDF_19               ; parameter
736
 
            push.parm
737
 
            call LET                    ; action call
738
 
 
739
 
TAG_35:
740
 
            set.line.number     35      ; current line number
741
 
 
742
 
TAG_40:
743
 
            set.line.number     40      ; current line number
744
 
   FOR_1         :                      ; start of FOR command
745
 
            ld hl, LIT_28               ; parameter
746
 
            push.parm
747
 
            ld hl, IDF_27               ; parameter
748
 
            push.parm
749
 
            call LET                    ; action call
750
 
            jp FOR.WHILE_1              ; jump to test if end of FOR
751
 
   FOR.STEP_1         :                 ; STEP action
752
 
            ld hl, LIT_31               ; parameter
753
 
            push.parm
754
 
            ld hl, IDF_19               ; parameter
755
 
            push.parm
756
 
            call MATH.MULT              ; action call
757
 
            ld hl, LIT_32               ; parameter
758
 
            push.parm
759
 
            call MATH.DIV               ; action call
760
 
            ld hl, IDF_27               ; parameter
761
 
            push.parm
762
 
            call MATH.ADD               ; action call
763
 
            ld hl, IDF_27               ; parameter
764
 
            push.parm
765
 
            call LET                    ; action call
766
 
   FOR.WHILE_1         :                ; test if end of FOR
767
 
            ld hl, IDF_27               ; parameter
768
 
            push.parm
769
 
            ld hl, LIT_36               ; parameter
770
 
            push.parm
771
 
            ld hl, IDF_19               ; parameter
772
 
            push.parm
773
 
            call MATH.MULT              ; action call
774
 
            call BOOLEAN.LE             ; action call
775
 
            call BOOLEAN.IF             ; verify IF condition result, out in A
776
 
            or a                        ; cp 0 = false
777
 
            jp z, ENDFOR_1              ; end the loop if while condition is false
778
 
   FOR.BODY_1         :                 ; start of FOR user code
779
 
 
780
 
TAG_45:
781
 
            set.line.number     45      ; current line number
782
 
 
783
 
TAG_50:
784
 
            set.line.number     50      ; current line number
785
 
   FOR_2         :                      ; start of FOR command
786
 
            ld hl, LIT_38               ; parameter
787
 
            push.parm
788
 
            ld hl, IDF_37               ; parameter
789
 
            push.parm
790
 
            call LET                    ; action call
791
 
            jp FOR.WHILE_2              ; jump to test if end of FOR
792
 
   FOR.STEP_2         :                 ; STEP action
793
 
            ld hl, LIT_39               ; parameter
794
 
            push.parm
795
 
            ld hl, IDF_37               ; parameter
796
 
            push.parm
797
 
            call MATH.ADD               ; action call
798
 
            ld hl, IDF_37               ; parameter
799
 
            push.parm
800
 
            call LET                    ; action call
801
 
   FOR.WHILE_2         :                ; test if end of FOR
802
 
            ld hl, IDF_37               ; parameter
803
 
            push.parm
804
 
            ld hl, LIT_40               ; parameter
805
 
            push.parm
806
 
            call BOOLEAN.LE             ; action call
807
 
            call BOOLEAN.IF             ; verify IF condition result, out in A
808
 
            or a                        ; cp 0 = false
809
 
            jp z, ENDFOR_2              ; end the loop if while condition is false
810
 
   FOR.BODY_2         :                 ; start of FOR user code
811
 
 
812
 
TAG_60:
813
 
            set.line.number     60      ; current line number
814
 
            ld hl, LIT_42               ; parameter
815
 
            push.parm
816
 
            ld hl, LIT_43               ; parameter
817
 
            push.parm
818
 
            ld hl, IDF_37               ; parameter
819
 
            push.parm
820
 
            call MATH.ADD               ; action call
821
 
            ld hl, IDF_27               ; parameter
822
 
            push.parm
823
 
            call SIN                    ; action call
824
 
            call MATH.MULT              ; action call
825
 
            call MATH.ADD               ; action call
826
 
            ld hl, IDF_41               ; parameter
827
 
            push.parm
828
 
            call LET                    ; action call
829
 
            ld hl, LIT_46               ; parameter
830
 
            push.parm
831
 
            ld hl, LIT_47               ; parameter
832
 
            push.parm
833
 
            ld hl, IDF_37               ; parameter
834
 
            push.parm
835
 
            call MATH.ADD               ; action call
836
 
            ld hl, IDF_27               ; parameter
837
 
            push.parm
838
 
            call COS                    ; action call
839
 
            call MATH.MULT              ; action call
840
 
            call MATH.ADD               ; action call
841
 
            ld hl, IDF_45               ; parameter
842
 
            push.parm
843
 
            call LET                    ; action call
844
 
 
845
 
TAG_70:
846
 
            set.line.number     70      ; current line number
847
 
   IF_1            :                    ; start of IF command
848
 
            ld hl, IDF_27               ; parameter
849
 
            push.parm
850
 
            ld hl, LIT_50               ; parameter
851
 
            push.parm
852
 
            call BOOLEAN.EQ             ; action call
853
 
              call BOOLEAN.IF           ; verify IF condition result, out in A
854
 
              or a                      ; cp 0 = false
855
 
              jp z, ELSE_1              ; if false, jump to ELSE actions
856
 
   THEN_1          :                    ; THEN actions
857
 
            jp TAG_90                   ; go to
858
 
              jp ENDIF_1                ; jump to END of IF command
859
 
   ELSE_1          :                    ; ELSE actions
860
 
   ENDIF_1         :                    ; end of IF command
861
 
 
862
 
TAG_80:
863
 
            set.line.number     80      ; current line number
864
 
            ld hl, LIT_59               ; parameter
865
 
            push.parm
866
 
            call PSET.COLOR             ; action call
867
 
            ld hl, IDF_45               ; parameter
868
 
            push.parm
869
 
            ld hl, IDF_41               ; parameter
870
 
            push.parm
871
 
            ld hl, IDF_57               ; parameter
872
 
            push.parm
873
 
            ld hl, IDF_56               ; parameter
874
 
            push.parm
875
 
            call PSET.XY                ; action call
876
 
            call LINE                   ; action call
877
 
 
878
 
TAG_85:
879
 
            set.line.number     85      ; current line number
880
 
 
881
 
TAG_90:
882
 
            set.line.number     90      ; current line number
883
 
            ld hl, IDF_41               ; parameter
884
 
            push.parm
885
 
            ld hl, IDF_56               ; parameter
886
 
            push.parm
887
 
            call LET                    ; action call
888
 
            ld hl, IDF_45               ; parameter
889
 
            push.parm
890
 
            ld hl, IDF_57               ; parameter
891
 
            push.parm
892
 
            call LET                    ; action call
893
 
 
894
 
TAG_100:
895
 
            set.line.number    100      ; current line number
896
 
              jp FOR.STEP_2             ; repeat actions
897
 
   ENDFOR_2         :                   ; END of FOR command
898
 
              jp FOR.STEP_1             ; repeat actions
899
 
   ENDFOR_1         :                   ; END of FOR command
900
 
 
901
 
TAG_105:
902
 
            set.line.number    105      ; current line number
903
 
 
904
 
TAG_110:
905
 
            set.line.number    110      ; current line number
906
 
   FOR_3         :                      ; start of FOR command
907
 
            ld hl, LIT_61               ; parameter
908
 
            push.parm
909
 
            ld hl, IDF_27               ; parameter
910
 
            push.parm
911
 
            call LET                    ; action call
912
 
            jp FOR.WHILE_3              ; jump to test if end of FOR
913
 
   FOR.STEP_3         :                 ; STEP action
914
 
            ld hl, LIT_62               ; parameter
915
 
            push.parm
916
 
            ld hl, IDF_19               ; parameter
917
 
            push.parm
918
 
            call MATH.MULT              ; action call
919
 
            ld hl, LIT_63               ; parameter
920
 
            push.parm
921
 
            call MATH.DIV               ; action call
922
 
            ld hl, IDF_27               ; parameter
923
 
            push.parm
924
 
            call MATH.ADD               ; action call
925
 
            ld hl, IDF_27               ; parameter
926
 
            push.parm
927
 
            call LET                    ; action call
928
 
   FOR.WHILE_3         :                ; test if end of FOR
929
 
            ld hl, IDF_27               ; parameter
930
 
            push.parm
931
 
            ld hl, LIT_64               ; parameter
932
 
            push.parm
933
 
            ld hl, IDF_19               ; parameter
934
 
            push.parm
935
 
            call MATH.MULT              ; action call
936
 
            call BOOLEAN.LE             ; action call
937
 
            call BOOLEAN.IF             ; verify IF condition result, out in A
938
 
            or a                        ; cp 0 = false
939
 
            jp z, ENDFOR_3              ; end the loop if while condition is false
940
 
   FOR.BODY_3         :                 ; start of FOR user code
941
 
 
942
 
TAG_120:
943
 
            set.line.number    120      ; current line number
944
 
            ld hl, LIT_65               ; parameter
945
 
            push.parm
946
 
            ld hl, LIT_66               ; parameter
947
 
            push.parm
948
 
            ld hl, IDF_27               ; parameter
949
 
            push.parm
950
 
            call SIN                    ; action call
951
 
            call MATH.MULT              ; action call
952
 
            call MATH.ADD               ; action call
953
 
            ld hl, IDF_41               ; parameter
954
 
            push.parm
955
 
            call LET                    ; action call
956
 
            ld hl, LIT_67               ; parameter
957
 
            push.parm
958
 
            ld hl, LIT_68               ; parameter
959
 
            push.parm
960
 
            ld hl, IDF_27               ; parameter
961
 
            push.parm
962
 
            call COS                    ; action call
963
 
            call MATH.MULT              ; action call
964
 
            call MATH.ADD               ; action call
965
 
            ld hl, IDF_45               ; parameter
966
 
            push.parm
967
 
            call LET                    ; action call
968
 
 
969
 
TAG_130:
970
 
            set.line.number    130      ; current line number
971
 
            ld hl, LIT_70               ; parameter
972
 
            push.parm
973
 
            ld hl, LIT_71               ; parameter
974
 
            push.parm
975
 
            ld hl, IDF_27               ; parameter
976
 
            push.parm
977
 
            ld hl, IDF_19               ; parameter
978
 
            push.parm
979
 
            ld hl, LIT_72               ; parameter
980
 
            push.parm
981
 
            call MATH.DIV               ; action call
982
 
            call MATH.ADD               ; action call
983
 
            call SIN                    ; action call
984
 
            call MATH.MULT              ; action call
985
 
            call MATH.ADD               ; action call
986
 
            ld hl, IDF_69               ; parameter
987
 
            push.parm
988
 
            call LET                    ; action call
989
 
            ld hl, LIT_74               ; parameter
990
 
            push.parm
991
 
            ld hl, LIT_75               ; parameter
992
 
            push.parm
993
 
            ld hl, IDF_27               ; parameter
994
 
            push.parm
995
 
            ld hl, IDF_19               ; parameter
996
 
            push.parm
997
 
            ld hl, LIT_76               ; parameter
998
 
            push.parm
999
 
            call MATH.DIV               ; action call
1000
 
            call MATH.ADD               ; action call
1001
 
            call COS                    ; action call
1002
 
            call MATH.MULT              ; action call
1003
 
            call MATH.ADD               ; action call
1004
 
            ld hl, IDF_73               ; parameter
1005
 
            push.parm
1006
 
            call LET                    ; action call
1007
 
 
1008
 
TAG_140:
1009
 
            set.line.number    140      ; current line number
1010
 
            ld hl, LIT_78               ; parameter
1011
 
            push.parm
1012
 
            ld hl, LIT_79               ; parameter
1013
 
            push.parm
1014
 
            ld hl, IDF_27               ; parameter
1015
 
            push.parm
1016
 
            ld hl, IDF_19               ; parameter
1017
 
            push.parm
1018
 
            ld hl, LIT_80               ; parameter
1019
 
            push.parm
1020
 
            call MATH.DIV               ; action call
1021
 
            call MATH.SUB               ; action call
1022
 
            call SIN                    ; action call
1023
 
            call MATH.MULT              ; action call
1024
 
            call MATH.ADD               ; action call
1025
 
            ld hl, IDF_77               ; parameter
1026
 
            push.parm
1027
 
            call LET                    ; action call
1028
 
            ld hl, LIT_83               ; parameter
1029
 
            push.parm
1030
 
            ld hl, LIT_84               ; parameter
1031
 
            push.parm
1032
 
            ld hl, IDF_27               ; parameter
1033
 
            push.parm
1034
 
            ld hl, IDF_19               ; parameter
1035
 
            push.parm
1036
 
            ld hl, LIT_85               ; parameter
1037
 
            push.parm
1038
 
            call MATH.DIV               ; action call
1039
 
            call MATH.SUB               ; action call
1040
 
            call COS                    ; action call
1041
 
            call MATH.MULT              ; action call
1042
 
            call MATH.ADD               ; action call
1043
 
            ld hl, IDF_82               ; parameter
1044
 
            push.parm
1045
 
            call LET                    ; action call
1046
 
 
1047
 
TAG_150:
1048
 
            set.line.number    150      ; current line number
1049
 
            ld hl, LIT_86               ; parameter
1050
 
            push.parm
1051
 
            call PSET.COLOR             ; action call
1052
 
            ld hl, IDF_45               ; parameter
1053
 
            push.parm
1054
 
            ld hl, IDF_41               ; parameter
1055
 
            push.parm
1056
 
            ld hl, IDF_73               ; parameter
1057
 
            push.parm
1058
 
            ld hl, IDF_69               ; parameter
1059
 
            push.parm
1060
 
            call PSET.XY                ; action call
1061
 
            call LINE                   ; action call
1062
 
            ld hl, LIT_87               ; parameter
1063
 
            push.parm
1064
 
            call PSET.COLOR             ; action call
1065
 
            ld hl, IDF_45               ; parameter
1066
 
            push.parm
1067
 
            ld hl, IDF_41               ; parameter
1068
 
            push.parm
1069
 
            ld hl, IDF_82               ; parameter
1070
 
            push.parm
1071
 
            ld hl, IDF_77               ; parameter
1072
 
            push.parm
1073
 
            call PSET.XY                ; action call
1074
 
            call LINE                   ; action call
1075
 
 
1076
 
TAG_155:
1077
 
            set.line.number    155      ; current line number
1078
 
 
1079
 
TAG_160:
1080
 
            set.line.number    160      ; current line number
1081
 
              jp FOR.STEP_3             ; repeat actions
1082
 
   ENDFOR_3         :                   ; END of FOR command
1083
 
 
1084
 
TAG_200:
1085
 
            set.line.number    200      ; current line number
1086
 
            jp TAG_200                  ; go to
1087
 
 
1088
 
;---------------------------------------------------------------------------------------------------------
1089
 
; PROGRAM END CODE
1090
 
;---------------------------------------------------------------------------------------------------------
1091
 
 
1092
 
    end_pgm:    __call_bios BIOS_DSPFNK      ; turn on function keys display
1093
 
                ld a, 1                      ;
1094
 
                ld (BIOS_CLIKSW), a          ; enable keyboard click
1095
 
 
1096
 
                if defined COMPILE_TO_ROM
1097
 
                    jp PROGRAM_TO_BASIC
1098
 
                else
1099
 
                    __call_basic BASIC_READYR    ; warm start Basic
1100
 
                endif
1101
 
 
1102
 
                ret                          ; end of the program
1103
 
 
1104
 
                ;__call_bios BIOS_GICINI      ; initialize sound system
1105
 
                ;if defined COMPILE_TO_DOS or defined COMPILE_TO_ROM
1106
 
                ;   __call_bios BIOS_RESET       ; restart Basic
1107
 
                ;else
1108
 
                ;   __call_basic BASIC_END       ; end to Basic
1109
 
                ;endif
1110
 
 
1111
 
 
1112
 
;---------------------------------------------------------------------------------------------------------
1113
 
; MSX BASIC KEYWORDS
1114
 
;---------------------------------------------------------------------------------------------------------
1115
 
 
1116
 
; keyword
1117
 
LET:
1118
 
 
1119
 
                    ; out IX = variable assigned address
1120
 
                    pop.parm                ; get variable address parameter
1121
 
                    push hl                 ; just to transfer hl to ix
1122
 
                    pop ix                  ;
1123
 
                    ld a, (ix)              ; get variable type
1124
 
                    cp 3                    ; test if string
1125
 
                    jr nz, LET.PARM         ; if not a string, it isn't necessary to free memory
1126
 
                    ld a, (ix + 3)          ; get variable string length
1127
 
                    or a                    ; cp 0
1128
 
                    jr z, LET.PARM          ; if zero, it isn't necessary to free memory
1129
 
                    ld c, (ix + 4)          ; get old string address low
1130
 
                    ld b, (ix + 5)          ; get old string address high
1131
 
                    push ix                 ; save variable address
1132
 
                      push bc               ; just to transfer bc (old string address) to ix
1133
 
                      pop ix                ;
1134
 
                      call memory.free      ; free memory
1135
 
                    pop ix                  ; restore variable address
1136
 
        LET.PARM:   pop.parm                ; get data address parameter (out hl = data address)
1137
 
                    ld a, (ix + 2)          ; get variable type flag
1138
 
                    or a                    ; cp 0 - test type flag (0=any, 255=fixed)
1139
 
                    jr nz, LET.FIXED        ; if type flag is fixed, so casting is necessary
1140
 
        LET.ANY:    push ix                 ; just to transfer ix (variable address) to de
1141
 
                    pop de                  ;
1142
 
                    ldi                     ; copy 1 byte from hl (data address) to de (variable address)
1143
 
                    inc de                  ; go to variable data area
1144
 
                    inc de                  ;
1145
 
                    inc hl                  ; go to data data area
1146
 
                    inc hl                  ;
1147
 
                    ld bc, 8                ; data = 8 bytes
1148
 
                    ldir                    ; copy bc bytes from hl (data address) to de (variable address)
1149
 
                    ld a, (ix)              ; get variable type
1150
 
                    cp 3                    ; test if string
1151
 
                    ret nz                  ; if not string, return
1152
 
                    jp LET.STRING           ; else do string treatment (in ix = variable address)
1153
 
        LET.FIXED:  push ix                 ; save variable destination address
1154
 
                            push hl                 ; save variable source address
1155
 
                      ld a, (ix)            ; get variable fixed type, and hl has parameter data address
1156
 
                      call CAST_TO          ; cast data to type (in hl = variable address, a = type to, out hl = casted data address)
1157
 
                                        pop de
1158
 
                    pop ix                  ; restore variable address
1159
 
                    ld a, (ix)              ; get variable destination type again
1160
 
                    cp 3                    ; test if string
1161
 
                    jr nz, LET.VALUE        ; if not string, do value treatment
1162
 
                                        ld a, (de)              ; get variable source type again
1163
 
                    cp 3                    ; test if string
1164
 
                    jr nz, LET.FIX1         ; if not string, get casted string size
1165
 
                                        inc de
1166
 
                                        inc de
1167
 
                                        inc de
1168
 
                                        ld a, (de)
1169
 
                                        ld (ix + 3), a          ; source string size
1170
 
                                        jr LET.FIX2
1171
 
                LET.FIX1:   push hl
1172
 
                              call GET_STR.LENGTH   ; get string length (in HL, out B)
1173
 
                                        pop hl
1174
 
                    ld (ix + 3), b          ; set variable length
1175
 
                LET.FIX2:   ld (ix + 4), l          ; casted data address low
1176
 
                    ld (ix + 5), h          ; casted data address high
1177
 
                    jp LET.STRING           ; do string treatment (in ix = variable address)
1178
 
        LET.VALUE:  push ix                 ; just to transfer ix (variable address) to de
1179
 
                    pop de                  ;
1180
 
                    inc de                  ; go to variable data area (and the data from its casted)
1181
 
                    inc de                  ;
1182
 
                    inc de                  ;
1183
 
                    ld bc, 8                ; data = 8 bytes
1184
 
                    ldir                    ; copy bc bytes from hl (data address) to de (variable address)
1185
 
                    ret                     ;
1186
 
        LET.STRING: ld a, (ix + 3)          ; string size
1187
 
                    or a                    ; cp 0 - test if null
1188
 
                    jr nz, LET.ALLOC        ; if not null, allocate new string (in ix = variable address)
1189
 
                    ld bc, LIT_NULL_STR     ; else, set to a null string literal
1190
 
                    ld (ix + 4), c          ; variable address low
1191
 
                    ld (ix + 5), b          ; variable address high
1192
 
                    ret                     ;
1193
 
        LET.ALLOC:  push ix                 ; save variable address
1194
 
                      ld l, (ix + 4)        ; source string address low
1195
 
                      ld h, (ix + 5)        ; source string address high
1196
 
                      push hl               ; save copy from address
1197
 
                        ld c, (ix + 3)      ; get variable length
1198
 
                        ld b, 0             ;
1199
 
                        inc bc              ; string length have one more byte from zero terminator
1200
 
                        push bc             ; save variable lenght + 1
1201
 
                          call memory.alloc ; in bc = size, out ix = address, nz=OK
1202
 
                                  jp z, memory.error
1203
 
                          push ix           ; just to transfer memory address from ix to de
1204
 
                          pop de            ;
1205
 
                        pop bc              ; restore bytes to be copied
1206
 
                      pop hl                ; restore copy from string address
1207
 
                      push de               ; save copy to address
1208
 
                        ldir                ; copy bc bytes from hl (data address) to de (variable address)
1209
 
                                                ;xor a
1210
 
                                                ;ld (de), a
1211
 
                      pop de                ; restore copy to address
1212
 
                    pop ix                  ; restore variable address
1213
 
                    ld (ix + 4), e          ; put memory address low into variable
1214
 
                    ld (ix + 5), d          ; put memory address high into variable
1215
 
                    ret                     ; variable assigned
1216
 
        
1217
 
; keyword
1218
 
BOOLEAN.IF:
1219
 
 
1220
 
                       pop.parm               ; get parameter boolean result in hl
1221
 
                       push hl                ; ix = hl
1222
 
                       pop ix                 ;
1223
 
                       ld a, (ix+5)           ; put boolean integer result in a
1224
 
                       ret                    ;
1225
 
        
1226
 
; keyword
1227
 
SCREEN:
1228
 
 
1229
 
                    pop.parm                ; get first parameter
1230
 
                    call CAST_TO.INT        ;
1231
 
                    call GET_INT.VALUE      ; output BC with integer value
1232
 
                    ld a, c                 ; A = screen number (0 to 3)
1233
 
                    cp 9
1234
 
                    jr c, SCREEN.1          ; if mode < 9, jump
1235
 
                    ld a, 8                 ; else, fix to 8
1236
 
         SCREEN.1:
1237
 
             if defined EXIST_DATA_SET
1238
 
                    call gfxSetScreenMode
1239
 
                    call gfxIsTileMode
1240
 
                    ret nz
1241
 
 
1242
 
                    jp gfxClearTileScreen
1243
 
             else
1244
 
                    jp gfxSetScreenMode
1245
 
             endif
1246
 
        
1247
 
; keyword
1248
 
BOX:
1249
 
 
1250
 
                    pop.parm                ; get first parameter
1251
 
                    call CAST_TO.INT        ;
1252
 
                    call GET_INT.VALUE      ; output BC with integer value
1253
 
                    ld (GFX_TEMP1), bc      ; dX
1254
 
                    pop.parm                ; get second parameter
1255
 
                    call CAST_TO.INT        ;
1256
 
                    call GET_INT.VALUE      ; output BC with integer value
1257
 
                    ;push bc                 ; dY
1258
 
                    ;pop de
1259
 
                                        ld d, b
1260
 
                                        ld e, c
1261
 
                    ld bc, (GFX_TEMP1)      ; dX
1262
 
                    xor a                   ; a = 0 (framed box)
1263
 
                    jp gfxDrawBox
1264
 
        
1265
 
; keyword
1266
 
PSET.XY:
1267
 
 
1268
 
                    pop.parm                ; get first parameter
1269
 
                    call CAST_TO.INT        ;
1270
 
                    call GET_INT.VALUE      ; output BC with integer value
1271
 
                    ld (BIOS_GRPACX), bc    ; X
1272
 
                    pop.parm                ; get second parameter
1273
 
                    call CAST_TO.INT        ;
1274
 
                    call GET_INT.VALUE      ; output BC with integer value
1275
 
                    ld (BIOS_GRPACY), bc    ; Y
1276
 
                    jp gfxRefreshXY
1277
 
        
1278
 
; keyword
1279
 
ATN:
1280
 
 
1281
 
                     pop.parm                 ; get parameter
1282
 
                             call COPY_TO.DAC         ; put in DAC
1283
 
                             and 12                   ; test if single/double
1284
 
                             jr nz, ATN.1             ; if already double
1285
 
                             __call_bios MATH_FRCDBL  ; convert DAC to double
1286
 
        ATN.1:       __call_bios MATH_ATN     ; get parameter from DAC and put result in DAC
1287
 
                     jp MATH.PARM.PUSH        ; return a dummy double variable from DAC
1288
 
        
1289
 
; keyword
1290
 
MATH.MULT:
1291
 
 
1292
 
                     call MATH.PARM.POP     ; get parameters into DAC/ARG
1293
 
                             ld a, (BASIC_VALTYP)   ;
1294
 
                             cp 2                   ; test if integer
1295
 
                             jp z, MATH.MULT.INT    ;
1296
 
                             cp 3                   ; test if string
1297
 
                             jp z, MATH.ERROR       ;
1298
 
                             cp 4                   ; test if single
1299
 
                             jp z, MATH.MULT.SGL    ;
1300
 
                             jp MATH.MULT.DBL       ; it is a double
1301
 
        
1302
 
; keyword
1303
 
FOR:
1304
 
; abstract virtual FOR
1305
 
; keyword
1306
 
MATH.ADD:
1307
 
 
1308
 
                     call MATH.PARM.POP     ; get parameters into DAC/ARG
1309
 
                             ld a, (BASIC_VALTYP)   ;
1310
 
                             cp 2                   ; test if integer
1311
 
                             jp z, MATH.ADD.INT     ;
1312
 
                             cp 3                   ; test if string
1313
 
                             jp z, STRING.CONCAT    ;
1314
 
                             cp 4                   ; test if single
1315
 
                             jp z, MATH.ADD.SGL     ;
1316
 
                             jp MATH.ADD.DBL        ; it is a double
1317
 
        
1318
 
; keyword
1319
 
MATH.DIV:
1320
 
 
1321
 
                     call MATH.PARM.POP     ; get parameters into DAC/ARG
1322
 
                             ld a, (BASIC_VALTYP)   ;
1323
 
                             cp 2                   ; test if integer
1324
 
                             jp z, MATH.DIV.INT     ;
1325
 
                             cp 3                   ; test if string
1326
 
                             jp z, MATH.ERROR       ;
1327
 
                             cp 4                   ; test if single
1328
 
                             jp z, MATH.DIV.SGL     ;
1329
 
                             jp MATH.DIV.DBL        ; it is a double
1330
 
        
1331
 
; keyword
1332
 
BOOLEAN.LE:
1333
 
 
1334
 
                     call MATH.PARM.POP     ; get parameters into DAC/ARG
1335
 
                             ld a, (BASIC_VALTYP)   ;
1336
 
                             cp 2                   ; test if integer
1337
 
                             jp z, BOOLEAN.LE.INT   ;
1338
 
                             cp 3                   ; test if string
1339
 
                             jp z, BOOLEAN.LE.STR   ;
1340
 
                             cp 4                   ; test if single
1341
 
                             jp z, BOOLEAN.LE.SGL   ;
1342
 
                             jp BOOLEAN.LE.DBL      ; it is a double
1343
 
        
1344
 
; keyword
1345
 
SIN:
1346
 
 
1347
 
                     pop.parm                 ; get parameter
1348
 
                             call COPY_TO.DAC         ; put in DAC
1349
 
                             and 12                   ; test if single/double
1350
 
                             jr nz, SIN.1             ; if already double
1351
 
                             __call_bios MATH_FRCDBL  ; convert DAC to double
1352
 
        SIN.1:       __call_bios MATH_SIN     ; get parameter from DAC and put result in DAC
1353
 
                     jp MATH.PARM.PUSH        ; return a dummy double variable from DAC
1354
 
        
1355
 
; keyword
1356
 
COS:
1357
 
 
1358
 
                     pop.parm                 ; get parameter
1359
 
                             call COPY_TO.DAC         ; put in DAC
1360
 
                             and 12                   ; test if single/double
1361
 
                             jr nz, COS.1             ; if already double
1362
 
                             __call_bios MATH_FRCDBL  ; convert DAC to double
1363
 
        COS.1:       __call_bios MATH_COS     ; get parameter from DAC and put result in DAC
1364
 
                     jp MATH.PARM.PUSH        ; return a dummy double variable from DAC
1365
 
        
1366
 
; keyword
1367
 
BOOLEAN.EQ:
1368
 
 
1369
 
                     call MATH.PARM.POP     ; get parameters into DAC/ARG
1370
 
                             ld a, (BASIC_VALTYP)   ;
1371
 
                             cp 2                   ; test if integer
1372
 
                             jp z, BOOLEAN.EQ.INT   ;
1373
 
                             cp 3                   ; test if string
1374
 
                             jp z, BOOLEAN.EQ.STR   ;
1375
 
                             cp 4                   ; test if single
1376
 
                             jp z, BOOLEAN.EQ.SGL   ;
1377
 
                             jp BOOLEAN.EQ.DBL      ; it is a double
1378
 
        
1379
 
; keyword
1380
 
GOTO:
1381
 
; abstract virtual GOTO
1382
 
; keyword
1383
 
LINE:
1384
 
 
1385
 
                    pop.parm                ; get first parameter
1386
 
                    call CAST_TO.INT        ;
1387
 
                    call GET_INT.VALUE      ; output BC with integer value
1388
 
                    ld (GFX_TEMP1), bc      ; dX
1389
 
                    pop.parm                ; get second parameter
1390
 
                    call CAST_TO.INT        ;
1391
 
                    call GET_INT.VALUE      ; output BC with integer value
1392
 
                    ;push bc                 ; dY
1393
 
                    ;pop de
1394
 
                                        ld d, b
1395
 
                                        ld e, c
1396
 
                    ld bc, (GFX_TEMP1)      ; dX
1397
 
                    jp gfxDrawLine
1398
 
        
1399
 
; keyword
1400
 
PSET.COLOR:
1401
 
 
1402
 
                    pop.parm                ; get first parameter
1403
 
                    call CAST_TO.INT        ;
1404
 
                    call GET_INT.VALUE      ; output BC with integer value
1405
 
                    ld a, c
1406
 
                    call gfxSetForeColor
1407
 
                    jp gfxSetColor
1408
 
        
1409
 
; keyword
1410
 
NEXT:
1411
 
; abstract virtual NEXT
1412
 
; keyword
1413
 
MATH.SUB:
1414
 
 
1415
 
                     call MATH.PARM.POP     ; get parameters into DAC/ARG
1416
 
                             ld a, (BASIC_VALTYP)   ;
1417
 
                             cp 2                   ; test if integer
1418
 
                             jp z, MATH.SUB.INT     ;
1419
 
                             cp 3                   ; test if string
1420
 
                             jp z, MATH.ERROR       ;
1421
 
                             cp 4                   ; test if single
1422
 
                             jp z, MATH.SUB.SGL     ;
1423
 
                             jp MATH.SUB.DBL        ; it is a double
1424
 
        
1425
 
 
1426
 
 
1427
 
;---------------------------------------------------------------------------------------------------------
1428
 
; MSX BASIC SUPPORT CODE
1429
 
;---------------------------------------------------------------------------------------------------------
1430
 
 
1431
 
if defined ON_ERROR or defined ON_INTERVAL or defined ON_KEY_START or defined ON_SPRITE or defined ON_STOP or defined ON_STRIG_START or defined TRAP_ENABLED or defined TRAP_DISABLED or defined TRAP_PAUSE or defined TRAP_UNPAUSE
1432
 
 
1433
 
RUN_TRAPS:    ld b, 26
1434
 
              ld hl, BASIC_TRPTBL
1435
 
RUN_TRAPS.1:  push hl
1436
 
                push bc
1437
 
                  call TRAP_HANDLER
1438
 
                pop bc
1439
 
              pop hl
1440
 
              inc hl
1441
 
              inc hl
1442
 
              inc hl
1443
 
              djnz RUN_TRAPS.1
1444
 
              ret
1445
 
 
1446
 
; in hl = trap block address (handle trap: sts=5? has handler? ackn, pause, run trap, sts=1? unpause)
1447
 
TRAP_HANDLER:
1448
 
                ld a, (hl)    ; trap status
1449
 
                cp 5          ; trap occured AND trap not paused AND trap enabled ?
1450
 
                ret nz        ; return if false
1451
 
                inc hl
1452
 
                ld e, (hl)    ; get trap address
1453
 
                inc hl
1454
 
                ld d, (hl)
1455
 
                dec hl
1456
 
                dec hl
1457
 
                ld a, d
1458
 
                or e
1459
 
                ret z         ; return if address zero
1460
 
                push hl
1461
 
                  __call_basic BASIC_TRAP_ACKNW
1462
 
                  __call_basic BASIC_TRAP_PAUSE
1463
 
                  ld hl, TRAP_HANDLER.1
1464
 
                  ld a, (BASIC_ONGSBF)  ; save traps execution
1465
 
                  push af
1466
 
                  xor a
1467
 
                  ld (BASIC_ONGSBF), a  ; disable traps execution
1468
 
                  push hl  ; next return will be to trap handler
1469
 
                  push de  ; indirect jump to trap address
1470
 
                  ret
1471
 
TRAP_HANDLER.1: pop af
1472
 
                ld (BASIC_ONGSBF), a    ; restore traps execution
1473
 
                pop hl
1474
 
                ld a, (hl)
1475
 
                cp 1       ; trap enabled?
1476
 
                ret z
1477
 
                __call_basic BASIC_TRAP_UNPAUSE
1478
 
                ret
1479
 
 
1480
 
; hl = trap block, de = trap handler
1481
 
SET_TRAP:       xor a
1482
 
                ld (hl), a                  ; trap block status
1483
 
                inc hl
1484
 
                ld (hl), e                  ; trap block handler (pointer)
1485
 
                inc hl
1486
 
                ld (hl), d
1487
 
                ret
1488
 
 
1489
 
endif
1490
 
 
1491
 
if defined SET_PLAY_VOICE_1 or defined SET_PLAY_VOICE_2 or defined SET_PLAY_VOICE_3 or defined DO_PLAY or defined MUSIC_PLAY or defined MUSIC_NEXT or defined MUSIC_STOP
1492
 
 
1493
 
   SET_PLAY_VOICE:
1494
 
        ld (BIOS_TEMP), a       ; save voice number
1495
 
        pop.parm
1496
 
                ld a, (hl)
1497
 
                cp 3
1498
 
                ret nz                  ; return if not string
1499
 
        call GET_STR.ADDR
1500
 
    SET_PLAY_VOICE.1:
1501
 
                ld (BIOS_TEMP2), a      ; save string size
1502
 
        push hl                 ; string address
1503
 
                  ld a, (BIOS_TEMP)     ; restore voice number
1504
 
                  call BIOS_GETVCP      ; get PSG voice buffer address (in A = voice number, out HL = address of byte 2)
1505
 
                pop de
1506
 
                ld a, (BIOS_TEMP2)      ; restore string size
1507
 
                ld (hl), a              ; string size
1508
 
                inc hl
1509
 
                ld (hl), e              ; string address
1510
 
                inc hl
1511
 
                ld (hl), d
1512
 
                inc hl
1513
 
        ld D,H                  ; voice stack
1514
 
        ld E,L
1515
 
        ld BC,001CH
1516
 
        add HL,BC
1517
 
        ex DE,HL
1518
 
        ld (HL),E
1519
 
        inc HL
1520
 
        ld (HL),D
1521
 
                ret
1522
 
 
1523
 
    START_PLAY:
1524
 
        ld HL, 0x752E
1525
 
        ld (BIOS_MCLTAB),HL
1526
 
        ld a, 1
1527
 
        ld (BIOS_MCLFLG),A
1528
 
        ld hl, BIOS_TEMP      ; voice count
1529
 
        ld a, 3
1530
 
        sub (hl)
1531
 
        dec a
1532
 
        ld (BIOS_PRSCNT), a
1533
 
        xor a
1534
 
        ld (BIOS_VOICEN), a
1535
 
        ld (BIOS_QUEUEN), a
1536
 
                ld (BIOS_MUSICF), a
1537
 
        ld HL,-12 ; -10
1538
 
                add HL,SP
1539
 
        ld (BIOS_SAVSP),HL
1540
 
                ld HL, BIOS_PLYCNT
1541
 
                ld (HL), 0
1542
 
                __call_basic BASIC_PLAY_DIRECT
1543
 
                ret
1544
 
 
1545
 
endif
1546
 
 
1547
 
 
1548
 
 
1549
 
;---------------------------------------------------------------------------------------------------------
1550
 
; VARIABLES ROUTINES
1551
 
;---------------------------------------------------------------------------------------------------------
1552
 
 
1553
 
; input hl = variable address
1554
 
; input bc = variable name
1555
 
; input d =  variable type
1556
 
INIT_VAR:          ld (hl), d    ; variable type
1557
 
                   inc hl
1558
 
                   ld (hl), c    ; variable name 1
1559
 
                   inc hl
1560
 
                   ld (hl), b    ; variable name 2
1561
 
                   ld a, d
1562
 
                   cp 3
1563
 
                   jp nz, CLEAR.VAR
1564
 
                   ld de, LIT_NULL_STR
1565
 
                   inc hl
1566
 
                   ld (hl), 0
1567
 
                   inc hl
1568
 
                   ld (hl), e
1569
 
                   inc hl
1570
 
                   ld (hl), d
1571
 
                   ld b, 5
1572
 
                   jr CLEAR.VAR.LOOP
1573
 
CLEAR.VAR:         ld b, 8
1574
 
CLEAR.VAR.LOOP:    inc hl
1575
 
                   ld (hl), 0    ; data address/value
1576
 
                   djnz CLEAR.VAR.LOOP
1577
 
                   ret
1578
 
; input HL = variable address
1579
 
; input A = variable output type
1580
 
; output HL = casted data address
1581
 
CAST_TO:           cp 2
1582
 
                   jp z, CAST_TO.INT
1583
 
                   cp 3
1584
 
                   jp z, CAST_TO.STR
1585
 
                   cp 4
1586
 
                   jp z, CAST_TO.SGL
1587
 
                   cp 8
1588
 
                   jp z, CAST_TO.DBL
1589
 
                   ret
1590
 
; input HL = variable address
1591
 
; output HL = variable address
1592
 
CAST_TO.INT:       ;push af
1593
 
                     ld a, (HL)
1594
 
                     cp 2
1595
 
                     jp z, GET_INT.ADDR
1596
 
                     cp 3
1597
 
                     jp z, CAST_STR_TO.INT
1598
 
                     cp 4
1599
 
                     jp z, CAST_SGL_TO.INT
1600
 
                     cp 8
1601
 
                     jp z, CAST_DBL_TO.INT
1602
 
                   ;pop af
1603
 
                   ret
1604
 
; input HL = variable address
1605
 
; output HL = variable address
1606
 
CAST_TO.STR:       ;push af
1607
 
                     ld a, (HL)
1608
 
                     cp 2
1609
 
                     jp z, CAST_INT_TO.STR
1610
 
                     cp 3
1611
 
                     jp z, GET_STR.ADDR
1612
 
                     cp 4
1613
 
                     jp z, CAST_SGL_TO.STR
1614
 
                     cp 8
1615
 
                     jp z, CAST_DBL_TO.STR
1616
 
                   ;pop af
1617
 
                   ret
1618
 
; input HL = variable address
1619
 
; output HL = variable address
1620
 
CAST_TO.SGL:       ;push af
1621
 
                     ld a, (HL)
1622
 
                     cp 2
1623
 
                     jp z, CAST_INT_TO.SGL
1624
 
                     cp 3
1625
 
                     jp z, CAST_STR_TO.SGL
1626
 
                     cp 4
1627
 
                     jp z, GET_SGL.ADDR
1628
 
                     cp 8
1629
 
                     jp z, CAST_DBL_TO.SGL
1630
 
                   ;pop af
1631
 
                   ret
1632
 
; input HL = variable address
1633
 
; output HL = variable address
1634
 
CAST_TO.DBL:       ;push af
1635
 
                     ld a, (hl)
1636
 
                     cp 2
1637
 
                     jp z, CAST_INT_TO.DBL
1638
 
                     cp 3
1639
 
                     jp z, CAST_STR_TO.DBL
1640
 
                     cp 4
1641
 
                     jp z, CAST_SGL_TO.DBL
1642
 
                     cp 8
1643
 
                     jp z, GET_DBL.ADDR
1644
 
                   ;pop af
1645
 
                   ret
1646
 
CAST_SGL_TO.STR:                           ; same as CAST_INT_TO.STR
1647
 
CAST_DBL_TO.STR:                           ; same as CAST_INT_TO.STR
1648
 
CAST_INT_TO.STR:   call COPY_TO.DAC
1649
 
                   xor a
1650
 
                   __call_bios MATH_FOUT    ; convert DAC to string
1651
 
                   ;pop af
1652
 
                   ret
1653
 
CAST_INT_TO.SGL:   call COPY_TO.DAC
1654
 
                   __call_bios MATH_FRCSGL
1655
 
                   ld hl, BASIC_DAC
1656
 
                   ret
1657
 
CAST_INT_TO.DBL:   call COPY_TO.DAC
1658
 
                   __call_bios MATH_FRCDBL
1659
 
                   ld hl, BASIC_DAC
1660
 
                   ret
1661
 
CAST_SGL_TO.INT:                           ; same as CAST_DBL_TO.INT
1662
 
CAST_DBL_TO.INT:   call COPY_TO.DAC
1663
 
                   __call_bios MATH_FRCINT
1664
 
                   ld hl, BASIC_DAC
1665
 
                   ret
1666
 
CAST_STR_TO.INT:   call CAST_STR_TO.VAL    ;
1667
 
                   __call_bios MATH_FRCINT ;
1668
 
                   ld hl, BASIC_DAC        ;
1669
 
                   ret                     ;
1670
 
CAST_STR_TO.SGL:   call CAST_STR_TO.VAL    ;
1671
 
                   __call_bios MATH_FRCSGL ;
1672
 
                   ld hl, BASIC_DAC        ;
1673
 
                   ret                     ;
1674
 
CAST_STR_TO.DBL:   call CAST_STR_TO.VAL    ;
1675
 
                   __call_bios MATH_FRCDBL ;
1676
 
                   ld hl, BASIC_DAC        ;
1677
 
                   ret                     ;
1678
 
CAST_STR_TO.VAL:   call GET_STR.ADDR       ;
1679
 
                   ld a, (hl)              ;
1680
 
                   __call_bios MATH_FIN    ; convert string to a value type
1681
 
                   ld hl, BASIC_DAC        ;
1682
 
                   ret                     ;
1683
 
GET_INT.VALUE:     inc hl                  ; output BC with integer value
1684
 
                   inc hl                  ;
1685
 
                   ld c, (hl)              ;
1686
 
                   inc hl                  ;
1687
 
                   ld b, (hl)              ;
1688
 
                   ret                     ;
1689
 
CAST_SGL_TO.DBL:                           ; same as GET_DBL.ADDR
1690
 
CAST_DBL_TO.SGL:                           ; same as GET_DBL.ADDR
1691
 
GET_INT.ADDR:                              ; same as GET_DBL.ADDR
1692
 
GET_SGL.ADDR:                              ; same as GET_DBL.ADDR
1693
 
GET_DBL.ADDR:      inc hl
1694
 
                   inc hl
1695
 
                   inc hl
1696
 
                   ;pop af
1697
 
                   ret
1698
 
GET_STR.ADDR:      push hl
1699
 
                   pop ix
1700
 
                                   ld a, (ix + 3)
1701
 
                   ld l, (ix + 4)
1702
 
                   ld h, (ix + 5)
1703
 
                   ret
1704
 
; input hl = string address
1705
 
; output b = string length
1706
 
GET_STR.LENGTH:    ld b, 0
1707
 
GET_STR.LEN.NEXT:  ld a, (hl)
1708
 
                   or a                     ; cp 0
1709
 
                   ret z
1710
 
                   inc b
1711
 
                   inc hl
1712
 
                   ld a, b
1713
 
                   cp 255
1714
 
                   jr z, GET_STR.LEN.ERR
1715
 
                   jr GET_STR.LEN.NEXT
1716
 
GET_STR.LEN.ERR:   ld b, 0
1717
 
                   ret
1718
 
STRING.COMPARE:    ld ix, (BASIC_DAC+1)     ; string 1
1719
 
                   ld iy, (BASIC_ARG+1)     ; string 2
1720
 
STRING.COMPARE.NX: ld a, (ix)               ; next char from string 1
1721
 
                   cp (iy)                  ; char s1 = char s2?
1722
 
                   jr nz, STRING.COMPARE.NE ; if not equal...
1723
 
                   cp 0                     ;
1724
 
                   jr z, STRING.COMPARE.F1  ; if string 1 has finished...
1725
 
                   ld a, (iy)               ; next char from string 2
1726
 
                   cp 0                     ;
1727
 
                   jr z, STRING.COMPARE.GT  ; if s2 has finished, s1 has not finished yet, so s1 is greater than s2
1728
 
                   inc ix                   ;
1729
 
                   inc iy                   ;
1730
 
                   jr STRING.COMPARE.NX     ; get next char pair
1731
 
STRING.COMPARE.F1: ld a, (iy)               ; verify if string 2 has finished too
1732
 
                   cp 0                     ;
1733
 
                   jr z, STRING.COMPARE.EQ  ; if s2 has finished, then they are equals
1734
 
                   jr STRING.COMPARE.LT     ; else, result = s1 is less than s2
1735
 
STRING.COMPARE.NE: jr c, STRING.COMPARE.GT  ; verify if s1 is greater than s2...
1736
 
STRING.COMPARE.LT: ld a, 1                  ; ...else, result = s1 less than s2
1737
 
                   ret                      ;
1738
 
STRING.COMPARE.GT: ld a, 0xFF               ; result = s1 is greater than s2
1739
 
                   ret                      ;
1740
 
STRING.COMPARE.EQ: xor a                    ; result = s1 is equal to s2
1741
 
                   ret                      ;
1742
 
STRING.CONCAT:     ld ix, BASIC_DAC           ; s1 size
1743
 
                                   ld a, (BASIC_ARG)          ; s2 size
1744
 
                                   add a, (ix)                ; s3 size = s1 size + s2 size
1745
 
                                   push af
1746
 
                     ld b, 0
1747
 
                     ld c, a                    ;
1748
 
                     inc bc                     ; add 1 byte to size
1749
 
                     call memory.alloc          ; in bc size, out ix new memory address, nz=OK
1750
 
                     jp z, memory.error         ;
1751
 
                     push ix                    ; save ix
1752
 
                       push ix                  ; save ix
1753
 
                       pop de                   ; de = ix
1754
 
                                           ld a, (BASIC_DAC)        ; s1 size
1755
 
                       ld hl, (BASIC_DAC + 1)   ; string 1
1756
 
                       call COPY_TO.STR         ; copy to new memory
1757
 
                                           ld a, (BASIC_ARG)        ; s2 size
1758
 
                       ld hl, (BASIC_ARG + 1)   ; string 2
1759
 
                       call COPY_TO.STR         ; copy to new memory
1760
 
                                           xor a
1761
 
                                           ld (de), a               ; null terminated
1762
 
                     pop hl                     ; hl = ix
1763
 
                   pop af
1764
 
                   call COPY_TO.VAR_DUMMY.STR ;
1765
 
                   ret.parm                   ; WARNING - VERIFY STRING MEMORY LEAKs
1766
 
STRING.PRINT:      ld a, (BIOS_SCRMOD)        ; 0=40x24 Text Mode, 1=32x24 Text Mode, 2=Graphics Mode, 3=Multicolour Mode
1767
 
                   cp 5                       ;
1768
 
                   jr nc, STRING.PRINT.G2     ; jump if graphic screen mode MSX2 (>=5)
1769
 
                   cp 2                       ;
1770
 
                   jr nc, STRING.PRINT.G1     ; jump if graphic screen mode MSX1 (>=2)
1771
 
STRING.PRINT.T:    ld a, (hl)                 ; get a char from a string parameter
1772
 
                   or a                       ; cp 0 - is it the string end?
1773
 
                   ret z                      ; exit if yes
1774
 
                   __call_bios BIOS_CHPUT     ; put the char (a) into text screen
1775
 
                   inc hl                     ; next char
1776
 
                   jr STRING.PRINT.T          ; repeat
1777
 
STRING.PRINT.G1:   ld a, (hl)                 ; get a char from a string parameter
1778
 
                   or a                       ; cp 0 - is it the string end?
1779
 
                   ret z                      ; exit if yes
1780
 
                   __call_bios BIOS_GRPPRT    ; put the char (a) into graphical screen
1781
 
                   inc hl                     ; next char
1782
 
                   jr STRING.PRINT.G1         ; repeat
1783
 
STRING.PRINT.G2:   ld a, (hl)                 ; get a char from a string parameter
1784
 
                   or a                       ; cp 0 - is it the string end?
1785
 
                   ret z                      ; exit if yes
1786
 
                   ld ix, BIOS_GRPPRT2        ; put the char (a) into graphical screen
1787
 
                   call BIOS_EXTROM
1788
 
                   inc hl                     ; next char
1789
 
                   jr STRING.PRINT.G2         ; repeat
1790
 
 
1791
 
; a = string size to copy
1792
 
; input hl = string from
1793
 
; input de = string to
1794
 
COPY_TO.STR:       or a
1795
 
                   ret z                      ; avoid copy if size = zero
1796
 
                   ld b, 0
1797
 
                   ld c, a                    ; string size
1798
 
                   ldir                       ; copy bc bytes from hl to de
1799
 
                   ret                        ;
1800
 
COPY_TO.BASIC_BUF: ld bc, BASIC_BUF
1801
 
                   ld a, (LIT_QUOTE_CHAR)
1802
 
                   ld (bc), a
1803
 
                   inc bc
1804
 
COPY_BAS_BUF.LOOP: ld a, (hl)
1805
 
                   or a                      ; cp 0
1806
 
                   jr z, COPY_BAS_BUF.EXIT
1807
 
                   ld (bc), a
1808
 
                   inc bc
1809
 
                   inc hl
1810
 
                   jr COPY_BAS_BUF.LOOP
1811
 
COPY_BAS_BUF.EXIT: ld a, (LIT_QUOTE_CHAR)
1812
 
                   ld (bc), a
1813
 
                   inc bc
1814
 
                   xor a
1815
 
                   ld (bc), a
1816
 
                   ld hl, BASIC_BUF
1817
 
                   ret
1818
 
COPY_TO.VAR_DUMMY:     ld a, (BASIC_VALTYP)    ; create dummy variable from VALTYPE
1819
 
                       cp 3                    ;
1820
 
                       jr nz, COPY_TO.VAR_DUMMY.DBL
1821
 
                                           push hl
1822
 
                                             call GET_STR.LENGTH   ; get string length
1823
 
                                           pop hl
1824
 
                       ld a, b                 ; string length
1825
 
COPY_TO.VAR_DUMMY.STR: call GET_VAR_DUMMY.ADDR ; create dummy string variable from HL
1826
 
                       ld (ix), 3            ; data type string
1827
 
                       ld (ix+1), 0          ;
1828
 
                       ld (ix+2), 255        ; var type fixed
1829
 
                       ld (ix+3), a          ; string length
1830
 
                       ld (ix+4), l          ; data address low
1831
 
                       ld (ix+5), h          ; data address high
1832
 
                       ;call GET_STR.LENGTH   ; get string length
1833
 
                       ;ld (ix+3), b          ; string length
1834
 
                       push ix               ; output var address...
1835
 
                       pop hl                ; ...into hl
1836
 
                       ret                   ;
1837
 
COPY_TO.VAR_DUMMY.INT: call GET_VAR_DUMMY.ADDR ; create dummy integer variable from BC
1838
 
                       ld (ix),    2           ; data type string
1839
 
                       ld (ix+1),  0           ;
1840
 
                       ld (ix+2),  0           ;
1841
 
                       ld (ix+3),  0           ;
1842
 
                       ld (ix+4),  0           ;
1843
 
                       ld (ix+5),  c           ;
1844
 
                       ld (ix+6),  b           ;
1845
 
                       ld (ix+7),  0           ;
1846
 
                       ld (ix+8),  0           ;
1847
 
                       ld (ix+9),  0           ;
1848
 
                       ld (ix+10), 0           ;
1849
 
                       push ix                 ; output var address...
1850
 
                       pop hl                  ; ...into hl
1851
 
                       ret                     ;
1852
 
COPY_TO.VAR_DUMMY.DBL: call GET_VAR_DUMMY.ADDR  ; create dummy value variable from DAC
1853
 
                       ld (ix), a            ; data type
1854
 
                       ld (ix+1), 0          ;
1855
 
                       ld (ix+2), 0          ;
1856
 
                       ld bc, 8              ;
1857
 
                       ld hl, BASIC_DAC      ;
1858
 
                       push ix               ; just to copy ix to de
1859
 
                       pop de                ;
1860
 
                       inc de                ;
1861
 
                       inc de                ;
1862
 
                       inc de                ;
1863
 
                       ldir                  ; copy bc bytes from hl (data address) to de (variable address)
1864
 
                       push ix               ; output var address...
1865
 
                       pop hl                ; ...into hl
1866
 
                       ret                   ;
1867
 
GET_VAR_DUMMY.ADDR:    push af                       ;
1868
 
                       push de
1869
 
                         ld de, 11                   ;
1870
 
                         ld ix, (VAR_DUMMY.POINTER)  ;
1871
 
                         ld a, (VAR_DUMMY.COUNTER)   ;
1872
 
GET_VAR_DUMMY.NEXT:      add ix, de                  ;
1873
 
                         inc a                       ;
1874
 
                         cp VAR_DUMMY.SIZE           ;
1875
 
                         jr nz, GET_VAR_DUMMY.EXIT   ;
1876
 
                           xor a                     ;
1877
 
                           ld ix, VAR_DUMMY.DATA     ;
1878
 
GET_VAR_DUMMY.EXIT:      ld (VAR_DUMMY.POINTER), ix  ;
1879
 
                         ld (VAR_DUMMY.COUNTER), a   ;
1880
 
                                                 ld a, (ix)                  ; get last var dummy type
1881
 
                                                 cp 3                        ; is it string?
1882
 
                                                 call z, GET_VAR_DUMMY.FREE  ; free string memory
1883
 
                       pop de
1884
 
                       pop af                        ;
1885
 
                       ret                           ;
1886
 
GET_VAR_DUMMY.FREE:
1887
 
                   push hl
1888
 
                   push ix
1889
 
                                     ld l, (ix+4)                    ; get string data address
1890
 
                                         ld h, (ix+5)
1891
 
                                         push hl
1892
 
                                         pop ix
1893
 
                     call memory.free      ; free memory
1894
 
                                   pop ix
1895
 
                                   pop hl
1896
 
                                   ret
1897
 
; input hl = variable address
1898
 
COPY_TO.DAC:       ld de, BASIC_DAC
1899
 
COPY_TO.DAC.DATA:  ld a, (hl)
1900
 
                   ld (BASIC_VALTYP), a
1901
 
                   inc hl
1902
 
                   inc hl
1903
 
                   inc hl
1904
 
                   ld bc, 8                ; data = 8 bytes
1905
 
                   ldir                    ; copy bc bytes from hl (data address) to de (variable address)
1906
 
                   ret
1907
 
COPY_TO.ARG:       ld de, BASIC_ARG        ;
1908
 
                   jr COPY_TO.DAC.DATA     ;
1909
 
COPY_TO.DAC_ARG:   ld hl, BASIC_DAC        ;
1910
 
                   ld de, BASIC_ARG        ;
1911
 
                   ld bc, 8                ; data = 8 bytes
1912
 
                   ldir                    ; copy bc bytes from hl (data address) to de (variable address)
1913
 
                   ret                     ;
1914
 
COPY_TO.ARG_DAC:   ld hl, BASIC_ARG        ;
1915
 
                   ld de, BASIC_DAC        ;
1916
 
                   ld bc, 8                ; data = 8 bytes
1917
 
                   ldir                    ; copy bc bytes from hl (data address) to de (variable address)
1918
 
                   ret                     ;
1919
 
COPY_TO.DAC_TMP:   ld hl, BASIC_DAC        ;
1920
 
                   ld de, BASIC_SWPTMP     ;
1921
 
                   ld bc, 8                ; data = 8 bytes
1922
 
                   ldir                    ; copy bc bytes from hl (data address) to de (variable address)
1923
 
                   ret                     ;
1924
 
COPY_TO.TMP_DAC:   ld hl, BASIC_SWPTMP     ;
1925
 
                   ld de, BASIC_DAC        ;
1926
 
                   ld bc, 8                ; data = 8 bytes
1927
 
                   ldir                    ; copy bc bytes from hl (data address) to de (variable address)
1928
 
                   ret                     ;
1929
 
SWAP.DAC.ARG:      di
1930
 
                   exx                     ; save registers
1931
 
                     ld bc, 8              ;
1932
 
                     ld hl, BASIC_DAC      ;
1933
 
                     ld de, BASIC_SWPTMP   ;
1934
 
                     ldir                  ; copy bc bytes from hl to de
1935
 
                     ld bc, 8              ;
1936
 
                     ld hl, BASIC_ARG      ;
1937
 
                     ld de, BASIC_DAC      ;
1938
 
                     ldir                  ; copy bc bytes from hl to de
1939
 
                     ld bc, 8              ;
1940
 
                     ld hl, BASIC_SWPTMP   ;
1941
 
                     ld de, BASIC_ARG      ;
1942
 
                     ldir                  ; copy bc bytes from hl to de
1943
 
                   exx                     ; restore registers
1944
 
                   ei
1945
 
                   ret                     ;
1946
 
CLEAR.DAC:         ld de, BASIC_DAC
1947
 
CLEAR.DAC.DATA:    ld hl, BASIC_VALTYP
1948
 
                   ld (hl), 2
1949
 
                   ld hl, LIT_NULL_DBL
1950
 
                   ld bc, 8                ; data = 8 bytes
1951
 
                   ldir                    ; copy bc bytes from hl (data address) to de (variable address)
1952
 
                   ret
1953
 
CLEAR.ARG:         ld de, BASIC_ARG
1954
 
                   jr CLEAR.DAC.DATA
1955
 
 
1956
 
 
1957
 
 
1958
 
;---------------------------------------------------------------------------------------------------------
1959
 
; MATH 16 BITS ROUTINES
1960
 
;---------------------------------------------------------------------------------------------------------
1961
 
 
1962
 
MATH.PARM.POP:  pop af                       ; get PC from caller stack
1963
 
                ex af, af'                   ; save PC to temp
1964
 
                  pop.parm                   ; get first parameter
1965
 
                  call COPY_TO.ARG           ; put HL in ARG (return var type in A)
1966
 
                  pop.parm                   ; get second parameter
1967
 
                ex af, af'                   ; restore PC from temp
1968
 
                push af                      ; put again PC from caller in stack
1969
 
                ex af, af'                   ; restore 1st data type
1970
 
                push af                      ; save 1st data type
1971
 
                  call COPY_TO.DAC           ; put HL in DAC (return var type in A)
1972
 
                pop bc                       ; restore 1st data type (ARG) in B
1973
 
                cp b                         ; test if data type in A (DAC) = data type in B (ARG)
1974
 
                ret z                        ; return if is equal data types
1975
 
MATH.PARM.CAST: push bc                      ; else cast both to double
1976
 
                  and 12                     ; test if single/double
1977
 
                  jr nz, MATH.PARM.CST1      ; avoid cast if already single/double
1978
 
                  __call_bios MATH_FRCDBL    ; convert DAC to double
1979
 
MATH.PARM.CST1: pop af                       ;
1980
 
                and 12                       ; test if single/double
1981
 
                jr nz, MATH.PARM.CST2        ; avoid cast if already single/double
1982
 
                ld (BASIC_VALTYP), a         ;
1983
 
                call COPY_TO.DAC_TMP         ;
1984
 
                call COPY_TO.ARG_DAC         ;
1985
 
                __call_bios MATH_FRCDBL      ; convert ARG to double
1986
 
                call COPY_TO.DAC_ARG         ;
1987
 
                call COPY_TO.TMP_DAC         ;
1988
 
MATH.PARM.CST2: ld a, 8                      ;
1989
 
                ld (BASIC_VALTYP), a         ;
1990
 
                ret                          ;
1991
 
MATH.PARM.POP.INT:                           ; return result in DAC/ARG as integer
1992
 
                pop af                       ; get PC from caller stack
1993
 
                  ex af, af'                 ; save PC to temp
1994
 
                    pop.parm                 ; get first parameter
1995
 
                    ld a, (hl)               ; get parameter type
1996
 
                    and 2                    ; test if integer
1997
 
                    jr z, MATH.PARM.POP.I1   ; do cast if not integer
1998
 
                    call COPY_TO.ARG         ; put HL in ARG (return var type in A)
1999
 
                    jr MATH.PARM.POP.I2      ; go to next parameter
2000
 
MATH.PARM.POP.I1:   call COPY_TO.DAC         ; put HL in DAC (return var type in A)
2001
 
                    __call_bios MATH_FRCINT  ; convert DAC to int
2002
 
                    call COPY_TO.DAC_ARG     ; copy DAC to ARG
2003
 
MATH.PARM.POP.I2:   pop.parm                 ; get second parameter
2004
 
                    call COPY_TO.DAC         ; put HL in DAC (return var type in A)
2005
 
                    and 2                    ; test if integer
2006
 
                    jr nz, MATH.PARM.POP.I3  ; avoid cast if already integer
2007
 
                    __call_bios MATH_FRCINT  ; convert DAC to int
2008
 
                    ld a, 2                  ;
2009
 
                    ld (BASIC_VALTYP), a     ;
2010
 
MATH.PARM.POP.I3:
2011
 
                    ex af, af'                 ; restore PC from temp
2012
 
                push af                      ; put again PC from caller in stack
2013
 
                ret                          ;
2014
 
MATH.PARM.PUSH: call COPY_TO.VAR_DUMMY       ;
2015
 
                ret.parm                     ;
2016
 
 
2017
 
if defined MATH.ADD
2018
 
 
2019
 
; input DAC, ARG
2020
 
; output in parm stack
2021
 
; http://www.z80.info/zip/zaks_book.pdf - page 104
2022
 
MATH.ADD.INT:  ld hl, (BASIC_DAC+2)  ;
2023
 
               ld bc, (BASIC_ARG+2)  ;
2024
 
               add hl, bc            ;
2025
 
               ld (BASIC_DAC+2), hl  ;
2026
 
               jp MATH.PARM.PUSH     ;
2027
 
 
2028
 
endif
2029
 
 
2030
 
if defined MATH.SUB or defined MATH.NEG
2031
 
 
2032
 
; input DAC, ARG
2033
 
; output in parm stack
2034
 
; http://www.z80.info/zip/zaks_book.pdf - page 104
2035
 
MATH.SUB.INT:  ld hl, (BASIC_DAC+2)  ;
2036
 
               ld de, (BASIC_ARG+2)  ;
2037
 
               and a                 ; clear carry
2038
 
               sbc hl, de            ;
2039
 
               ld (BASIC_DAC+2), hl  ;
2040
 
               jp MATH.PARM.PUSH     ;
2041
 
 
2042
 
endif
2043
 
 
2044
 
if defined MATH.MULT
2045
 
 
2046
 
; input DAC, ARG
2047
 
; output in parm stack
2048
 
MATH.MULT.INT: ld hl, (BASIC_DAC+2)  ;
2049
 
               ld bc, (BASIC_ARG+2)  ;
2050
 
               call MATH.MULT.16     ;
2051
 
               ld (BASIC_DAC+2), hl  ;
2052
 
               jp MATH.PARM.PUSH     ;
2053
 
 
2054
 
; input HL = multiplicand
2055
 
; input BC = multiplier
2056
 
; output HL = result
2057
 
; http://www.z80.info/zip/zaks_book.pdf - page 131
2058
 
MATH.MULT.16:  ld a, c                          ; low multiplier
2059
 
               ld c, b                          ; high multiplier
2060
 
               ld b, 16
2061
 
               ld d, h                  ; multiplicand
2062
 
               ld e, l
2063
 
               ld hl, 0
2064
 
MULT16LOOP:    srl c                            ; right shift multiplier high
2065
 
               rra                                      ; rotate right multiplier low
2066
 
               jr nc, MULT16NOADD       ; test carry
2067
 
               add hl, de                       ; add multiplicand to result
2068
 
MULT16NOADD:   ex de, hl
2069
 
               add hl, hl                       ; double - shift multiplicand
2070
 
               ex de, hl
2071
 
               djnz MULT16LOOP
2072
 
               ret
2073
 
 
2074
 
endif
2075
 
 
2076
 
if defined MATH.DIV or defined MATH.IDIV or defined MATH.MOD
2077
 
 
2078
 
; input AC = dividend
2079
 
; input DE = divisor
2080
 
; output AC = quotient
2081
 
; output HL = remainder
2082
 
; http://www.z80.info/zip/zaks_book.pdf - page 140
2083
 
MATH.DIV.16:   ld hl, 0                         ; clear accumulator
2084
 
               ld b, 16                         ; set counter
2085
 
DIV16LOOP:     rl c                                     ; rotate accumulator result left
2086
 
               rla
2087
 
               adc hl, hl                               ; left shift
2088
 
               sbc hl, de                               ; trial subtract divisor
2089
 
               jr nc, $ + 3                     ; subtract was OK ($ = current location)
2090
 
               add hl, de                               ; restore accumulator
2091
 
               ccf                                              ; calculate result bit
2092
 
               djnz DIV16LOOP                   ; counter not zero
2093
 
               rl c                                     ; shift in last result bit
2094
 
               rla
2095
 
               ret
2096
 
 
2097
 
endif
2098
 
 
2099
 
if defined GFX_FAST or defined LINE
2100
 
 
2101
 
; compare two signed 16 bits integers
2102
 
; HL < DE: Carry flag
2103
 
; HL = DE: Zero flag
2104
 
; http://www.z80.info/zip/zaks_book.pdf - page 531
2105
 
MATH.COMP.S16: ld a, h                       ; test high order byte
2106
 
               and 0x80                      ; test sign, clear carry
2107
 
                           jr nz, MATH.COMP.S16.NEGM1    ; jump if hl is negative
2108
 
                           bit 7, d
2109
 
                           ret nz                        ; de is negative (and hl is positive)
2110
 
                           ld a, h
2111
 
                           cp d                          ; signs are both positive, so normal compare
2112
 
                           ret nz
2113
 
                           ld a, l                       ; test low order byte
2114
 
                           cp e
2115
 
               ret
2116
 
MATH.COMP.S16.NEGM1:
2117
 
               xor d
2118
 
               rla                           ; sign bit into carry
2119
 
               ret c                         ; signs different
2120
 
               ld a, h
2121
 
               cp d                          ; both signs negative
2122
 
                           ret nz
2123
 
                           ld a, l
2124
 
                           cp e
2125
 
                           ret
2126
 
 
2127
 
endif
2128
 
 
2129
 
if defined MATH.ADD
2130
 
 
2131
 
MATH.ADD.SGL:  ld a, 8                  ;
2132
 
               ld (BASIC_VALTYP), a     ;
2133
 
MATH.ADD.DBL:  __call_bios MATH_DECADD  ;
2134
 
               jp MATH.PARM.PUSH        ;
2135
 
 
2136
 
endif
2137
 
 
2138
 
if defined MATH.SUB or defined MATH.NEG
2139
 
 
2140
 
MATH.SUB.SGL:  ld a, 8                  ;
2141
 
               ld (BASIC_VALTYP), a     ;
2142
 
MATH.SUB.DBL:  __call_bios MATH_DECSUB  ;
2143
 
               jp MATH.PARM.PUSH        ;
2144
 
 
2145
 
endif
2146
 
 
2147
 
if defined MATH.MULT
2148
 
 
2149
 
MATH.MULT.SGL: ld a, 8                  ;
2150
 
               ld (BASIC_VALTYP), a     ;
2151
 
MATH.MULT.DBL: __call_bios MATH_DECMUL  ;
2152
 
               jp MATH.PARM.PUSH        ;
2153
 
 
2154
 
endif
2155
 
 
2156
 
if defined MATH.DIV
2157
 
 
2158
 
; input DAC, ARG
2159
 
; output in parm stack
2160
 
MATH.DIV.INT:  __call_bios MATH_FRCDBL  ; convert DAC to double
2161
 
               call SWAP.DAC.ARG        ;
2162
 
               ld a, 2                  ;
2163
 
               ld (BASIC_VALTYP), a     ;
2164
 
               __call_bios MATH_FRCDBL  ; convert ARG to double
2165
 
               call SWAP.DAC.ARG        ;
2166
 
MATH.DIV.SGL:  ld a, 8                  ;
2167
 
               ld (BASIC_VALTYP), a     ;
2168
 
MATH.DIV.DBL:  __call_bios MATH_DECDIV  ;
2169
 
               jp MATH.PARM.PUSH        ;
2170
 
 
2171
 
endif
2172
 
 
2173
 
if defined MATH.IDIV
2174
 
 
2175
 
; input DAC, ARG
2176
 
; output in parm stack
2177
 
MATH.IDIV.SGL: ld a, 8                  ;
2178
 
               ld (BASIC_VALTYP), a     ;
2179
 
MATH.IDIV.DBL: __call_bios MATH_FRCINT  ; convert DAC to integer
2180
 
               call SWAP.DAC.ARG        ;
2181
 
               ld a, 8                  ;
2182
 
               ld (BASIC_VALTYP), a     ;
2183
 
               __call_bios MATH_FRCINT  ; convert ARG to integer
2184
 
               call SWAP.DAC.ARG        ;
2185
 
MATH.IDIV.INT: ld hl, (BASIC_DAC+2)     ;
2186
 
               ld a, h                  ;
2187
 
               ld c, l                  ;
2188
 
               ld de, (BASIC_ARG+2)     ;
2189
 
               call MATH.DIV.16         ;
2190
 
               ld h, a                  ;
2191
 
               ld l, c                  ;
2192
 
               ld (BASIC_DAC+2), hl     ; quotient
2193
 
               jp MATH.PARM.PUSH        ;
2194
 
 
2195
 
endif
2196
 
 
2197
 
if defined MATH.POW
2198
 
 
2199
 
MATH.POW.INT:  ld (BASIC_VALTYP), a     ;
2200
 
               __call_bios MATH_FRCDBL  ; convert DAC to double
2201
 
               call SWAP.DAC.ARG        ;
2202
 
               ld a, 2                  ;
2203
 
               ld (BASIC_VALTYP), a     ;
2204
 
               __call_bios MATH_FRCDBL  ; convert ARG to double
2205
 
               call SWAP.DAC.ARG        ;
2206
 
MATH.POW.SGL:  ld a, 8                  ;
2207
 
               ld (BASIC_VALTYP), a     ;
2208
 
MATH.POW.DBL:  __call_bios MATH_DBLEXP  ;
2209
 
               jp MATH.PARM.PUSH        ;
2210
 
 
2211
 
endif
2212
 
 
2213
 
if defined MATH.MOD
2214
 
 
2215
 
;MATH.MOD.SGL:  ld a, 8                  ;
2216
 
;               ld (BASIC_VALTYP), a     ;
2217
 
;MATH.MOD.DBL:  __call_bios MATH_FRCINT  ; convert DAC to integer
2218
 
;               call SWAP.DAC.ARG        ;
2219
 
;                        ld a, 8                  ;
2220
 
;               ld (BASIC_VALTYP), a     ;
2221
 
;               __call_bios MATH_FRCINT  ; convert ARG to integer
2222
 
;               call SWAP.DAC.ARG        ;
2223
 
MATH.MOD.INT:  ld hl, (BASIC_DAC+2)     ;
2224
 
               ld a, h                  ;
2225
 
               ld c, l                  ;
2226
 
               ld de, (BASIC_ARG+2)     ;
2227
 
               call MATH.DIV.16         ;
2228
 
               ld (BASIC_DAC+2), hl     ; remainder
2229
 
               jp MATH.PARM.PUSH        ;
2230
 
 
2231
 
endif
2232
 
 
2233
 
if defined ISQR
2234
 
 
2235
 
; fast 16-bit integer square root
2236
 
; http://www.retroprogramming.com/2017/07/a-fast-z80-integer-square-root.html
2237
 
; 92 bytes, 344-379 cycles (average 362)
2238
 
; v2 - 3 t-state optimization spotted by Russ McNulty
2239
 
; call with hl = number to square root
2240
 
; returns    a = square root
2241
 
; corrupts  hl, de
2242
 
 
2243
 
MATH.INT.SQR:
2244
 
  ld a,h
2245
 
  ld de,0B0C0h
2246
 
  add a,e
2247
 
  jr c,sq7
2248
 
  ld a,h
2249
 
  ld d,0F0h
2250
 
sq7:
2251
 
  add a,d
2252
 
  jr nc,sq6
2253
 
  res 5,d
2254
 
  db 254
2255
 
sq6:
2256
 
  sub d
2257
 
  sra d
2258
 
  set 2,d
2259
 
  add a,d
2260
 
  jr nc,sq5
2261
 
  res 3,d
2262
 
  db 254
2263
 
sq5:
2264
 
  sub d
2265
 
  sra d
2266
 
  inc d
2267
 
  add a,d
2268
 
  jr nc,sq4
2269
 
  res 1,d
2270
 
  db 254
2271
 
sq4:
2272
 
  sub d
2273
 
  sra d
2274
 
  ld h,a
2275
 
  add hl,de
2276
 
  jr nc,sq3
2277
 
  ld e,040h
2278
 
  db 210
2279
 
sq3:
2280
 
  sbc hl,de
2281
 
  sra d
2282
 
  ld a,e
2283
 
  rra
2284
 
  or 010h
2285
 
  ld e,a
2286
 
  add hl,de
2287
 
  jr nc,sq2
2288
 
  and 0DFh
2289
 
  db 218
2290
 
sq2:
2291
 
  sbc hl,de
2292
 
  sra d
2293
 
  rra
2294
 
  or 04h
2295
 
  ld e,a
2296
 
  add hl,de
2297
 
  jr nc,sq1
2298
 
  and 0F7h
2299
 
  db 218
2300
 
sq1:
2301
 
  sbc hl,de
2302
 
  sra d
2303
 
  rra
2304
 
  inc a
2305
 
  ld e,a
2306
 
  add hl,de
2307
 
  jr nc,sq0
2308
 
  and 0FDh
2309
 
sq0:
2310
 
  sra d
2311
 
  rra
2312
 
  cpl
2313
 
  ret
2314
 
 
2315
 
endif
2316
 
 
2317
 
if defined RANDOMIZE or defined SEED
2318
 
 
2319
 
MATH.RANDOMIZE:    di                          ;
2320
 
                     ld bc, (BIOS_JIFFY)       ;
2321
 
                   ei                          ;
2322
 
 
2323
 
MATH.SEED:         ld (BASIC_RNDX), bc         ; seed to IRND
2324
 
                   push bc                     ; in bc = new integer seed
2325
 
                     call CLEAR.DAC            ;
2326
 
                   pop bc                      ;
2327
 
                   ;ld ix, BASIC_DAC            ;
2328
 
                   ld (BASIC_DAC+2), bc        ; copy bc to dac
2329
 
                   ld a, 2                     ; type integer
2330
 
                   ld (BASIC_VALTYP), a        ;
2331
 
                   __call_bios MATH_FRCDBL     ; convert DAC integer to DAC double
2332
 
                   __call_bios MATH_NEG        ; DAC = -DAC
2333
 
                   __call_bios MATH_RND        ; put in DAC a new random number from previous DAC parameter
2334
 
                   ret                         ;
2335
 
 
2336
 
endif
2337
 
 
2338
 
MATH.ERROR:        ld e, 13                          ; type mismatch
2339
 
                   __call_basic BASIC_ERROR_HANDLER  ;
2340
 
                   ret
2341
 
 
2342
 
 
2343
 
;---------------------------------------------------------------------------------------------------------
2344
 
; BOOLEAN ROUTINES
2345
 
;---------------------------------------------------------------------------------------------------------
2346
 
 
2347
 
BOOLEAN.RET.TRUE:  ld hl, LIT_TRUE             ;
2348
 
                   ret.parm                    ;
2349
 
BOOLEAN.RET.FALSE: ld hl, LIT_FALSE            ;
2350
 
                   ret.parm                    ;
2351
 
BOOLEAN.CMP.INT:   ld hl, (BASIC_DAC+2)        ;
2352
 
                   ld de, (BASIC_ARG+2)        ;
2353
 
                   __call_bios MATH_ICOMP      ;
2354
 
                   ret                         ;
2355
 
BOOLEAN.CMP.SGL:   ld bc, (BASIC_ARG)          ;
2356
 
                   ld de, (BASIC_ARG+2)        ;
2357
 
                   __call_bios MATH_DCOMP      ;
2358
 
                   ret                         ;
2359
 
BOOLEAN.CMP.DBL:   __call_bios MATH_XDCOMP     ;
2360
 
                   ret                         ;
2361
 
BOOLEAN.CMP.STR:   call STRING.COMPARE         ;
2362
 
                   ret                         ;
2363
 
 
2364
 
if defined BOOLEAN.GT
2365
 
 
2366
 
BOOLEAN.GT.INT:    call BOOLEAN.CMP.INT        ;
2367
 
                   jr BOOLEAN.GT.RET           ;
2368
 
BOOLEAN.GT.STR:    call BOOLEAN.CMP.STR        ;
2369
 
                   jr BOOLEAN.GT.RET           ;
2370
 
BOOLEAN.GT.SGL:    call BOOLEAN.CMP.SGL        ;
2371
 
                   jr BOOLEAN.GT.RET           ;
2372
 
BOOLEAN.GT.DBL:    call BOOLEAN.CMP.DBL        ;
2373
 
                   jr BOOLEAN.GT.RET           ;
2374
 
BOOLEAN.GT.RET:    cp 0x01                     ;
2375
 
                   jp z, BOOLEAN.RET.TRUE      ;
2376
 
                   jp BOOLEAN.RET.FALSE        ;
2377
 
endif
2378
 
 
2379
 
if defined BOOLEAN.LT
2380
 
 
2381
 
BOOLEAN.LT.INT:    call BOOLEAN.CMP.INT        ;
2382
 
                   jr BOOLEAN.LT.RET           ;
2383
 
BOOLEAN.LT.STR:    call BOOLEAN.CMP.STR        ;
2384
 
                   jr BOOLEAN.LT.RET           ;
2385
 
BOOLEAN.LT.SGL:    call BOOLEAN.CMP.SGL        ;
2386
 
                   jr BOOLEAN.LT.RET           ;
2387
 
BOOLEAN.LT.DBL:    call BOOLEAN.CMP.DBL        ;
2388
 
                   jr BOOLEAN.LT.RET           ;
2389
 
BOOLEAN.LT.RET:    cp 0xFF                     ;
2390
 
                   jp z, BOOLEAN.RET.TRUE      ;
2391
 
                   jp BOOLEAN.RET.FALSE        ;
2392
 
 
2393
 
endif
2394
 
 
2395
 
if defined BOOLEAN.GE
2396
 
 
2397
 
BOOLEAN.GE.INT:    call BOOLEAN.CMP.INT        ;
2398
 
                   jr BOOLEAN.GE.RET           ;
2399
 
BOOLEAN.GE.STR:    call BOOLEAN.CMP.STR        ;
2400
 
                   jr BOOLEAN.GE.RET           ;
2401
 
BOOLEAN.GE.SGL:    call BOOLEAN.CMP.SGL        ;
2402
 
                   jr BOOLEAN.GE.RET           ;
2403
 
BOOLEAN.GE.DBL:    call BOOLEAN.CMP.DBL        ;
2404
 
                   jr BOOLEAN.GE.RET           ;
2405
 
BOOLEAN.GE.RET:    cp 0x01                     ;
2406
 
                   jp z, BOOLEAN.RET.TRUE      ;
2407
 
                   or a                        ; cp 0
2408
 
                   jp z, BOOLEAN.RET.TRUE      ;
2409
 
                   jp BOOLEAN.RET.FALSE        ;
2410
 
 
2411
 
endif
2412
 
 
2413
 
if defined BOOLEAN.LE
2414
 
 
2415
 
BOOLEAN.LE.INT:    call BOOLEAN.CMP.INT        ;
2416
 
                   jr BOOLEAN.LE.RET           ;
2417
 
BOOLEAN.LE.STR:    call BOOLEAN.CMP.STR        ;
2418
 
                   jr BOOLEAN.LE.RET           ;
2419
 
BOOLEAN.LE.SGL:    call BOOLEAN.CMP.SGL        ;
2420
 
                   jr BOOLEAN.LE.RET           ;
2421
 
BOOLEAN.LE.DBL:    call BOOLEAN.CMP.DBL        ;
2422
 
                   jr BOOLEAN.LE.RET           ;
2423
 
BOOLEAN.LE.RET:    cp 0xFF                     ;
2424
 
                   jp z, BOOLEAN.RET.TRUE      ;
2425
 
                   or a                        ; cp 0
2426
 
                   jp z, BOOLEAN.RET.TRUE      ;
2427
 
                   jp BOOLEAN.RET.FALSE        ;
2428
 
 
2429
 
endif
2430
 
 
2431
 
if defined BOOLEAN.NE
2432
 
 
2433
 
BOOLEAN.NE.INT:    call BOOLEAN.CMP.INT        ;
2434
 
                   jr BOOLEAN.NE.RET           ;
2435
 
BOOLEAN.NE.STR:    call BOOLEAN.CMP.STR        ;
2436
 
                   jr BOOLEAN.NE.RET           ;
2437
 
BOOLEAN.NE.SGL:    call BOOLEAN.CMP.SGL        ;
2438
 
                   jr BOOLEAN.NE.RET           ;
2439
 
BOOLEAN.NE.DBL:    call BOOLEAN.CMP.DBL        ;
2440
 
                   jr BOOLEAN.NE.RET           ;
2441
 
BOOLEAN.NE.RET:    or a                        ; cp 0
2442
 
                   jp nz, BOOLEAN.RET.TRUE     ;
2443
 
                   jp BOOLEAN.RET.FALSE        ;
2444
 
 
2445
 
endif
2446
 
 
2447
 
if defined BOOLEAN.EQ
2448
 
 
2449
 
BOOLEAN.EQ.INT:    call BOOLEAN.CMP.INT        ;
2450
 
                   jr BOOLEAN.EQ.RET           ;
2451
 
BOOLEAN.EQ.STR:    call BOOLEAN.CMP.STR        ;
2452
 
                   jr BOOLEAN.EQ.RET           ;
2453
 
BOOLEAN.EQ.SGL:    call BOOLEAN.CMP.SGL        ;
2454
 
                   jr BOOLEAN.EQ.RET           ;
2455
 
BOOLEAN.EQ.DBL:    call BOOLEAN.CMP.DBL        ;
2456
 
                   jr BOOLEAN.EQ.RET           ;
2457
 
BOOLEAN.EQ.RET:    or a                        ; cp 0
2458
 
                   jp z, BOOLEAN.RET.TRUE      ;
2459
 
                   jp BOOLEAN.RET.FALSE        ;
2460
 
 
2461
 
endif
2462
 
 
2463
 
if defined BOOLEAN.AND
2464
 
 
2465
 
BOOLEAN.AND.INT:   ld a, (BASIC_DAC+2)         ;
2466
 
                   ld hl, BASIC_ARG+2          ;
2467
 
                   and (hl)                    ;
2468
 
                   ld (BASIC_DAC+2), a         ;
2469
 
                   inc hl                      ;
2470
 
                   ld a, (BASIC_DAC+3)         ;
2471
 
                   and (hl)                    ;
2472
 
                   ld (BASIC_DAC+3), a         ;
2473
 
                   ld a, 2                     ;
2474
 
                   jp MATH.PARM.PUSH           ;
2475
 
 
2476
 
endif
2477
 
 
2478
 
if defined BOOLEAN.OR
2479
 
 
2480
 
BOOLEAN.OR.INT:    ld a, (BASIC_DAC+2)         ;
2481
 
                   ld hl, BASIC_ARG+2          ;
2482
 
                   or (hl)                     ;
2483
 
                   ld (BASIC_DAC+2), a         ;
2484
 
                   inc hl                      ;
2485
 
                   ld a, (BASIC_DAC+3)         ;
2486
 
                   or (hl)                     ;
2487
 
                   ld (BASIC_DAC+3), a         ;
2488
 
                   ld a, 2                     ;
2489
 
                   jp MATH.PARM.PUSH           ;
2490
 
 
2491
 
endif
2492
 
 
2493
 
if defined BOOLEAN.XOR
2494
 
 
2495
 
BOOLEAN.XOR.INT:   ld a, (BASIC_DAC+2)         ;
2496
 
                   ld hl, BASIC_ARG+2          ;
2497
 
                   xor (hl)                    ;
2498
 
                   ld (BASIC_DAC+2), a         ;
2499
 
                   inc hl                      ;
2500
 
                   ld a, (BASIC_DAC+3)         ;
2501
 
                   xor (hl)                    ;
2502
 
                   ld (BASIC_DAC+3), a         ;
2503
 
                   ld a, 2                     ;
2504
 
                   jp MATH.PARM.PUSH           ;
2505
 
 
2506
 
endif
2507
 
 
2508
 
if defined BOOLEAN.EQV
2509
 
 
2510
 
BOOLEAN.EQV.INT:   ld a, (BASIC_DAC+2)         ;
2511
 
                   ld hl, BASIC_ARG+2          ;
2512
 
                   xor (hl)                    ;
2513
 
                   cpl                         ;
2514
 
                   ld (BASIC_DAC+2), a         ;
2515
 
                   inc hl                      ;
2516
 
                   ld a, (BASIC_DAC+3)         ;
2517
 
                   xor (hl)                    ;
2518
 
                   cpl                         ;
2519
 
                   ld (BASIC_DAC+3), a         ;
2520
 
                   ld a, 2                     ;
2521
 
                   jp MATH.PARM.PUSH           ;
2522
 
 
2523
 
endif
2524
 
 
2525
 
if defined BOOLEAN.IMP
2526
 
 
2527
 
BOOLEAN.IMP.INT:   ld a, (BASIC_DAC+2)         ;
2528
 
                   ld hl, BASIC_ARG+2          ;
2529
 
                   cpl                         ;
2530
 
                   or (hl)                     ;
2531
 
                   ld (BASIC_DAC+2), a         ;
2532
 
                   inc hl                      ;
2533
 
                   ld a, (BASIC_DAC+3)         ;
2534
 
                   cpl                         ;
2535
 
                   or (hl)                     ;
2536
 
                   ld (BASIC_DAC+3), a         ;
2537
 
                   ld a, 2                     ;
2538
 
                   jp MATH.PARM.PUSH           ;
2539
 
 
2540
 
endif
2541
 
 
2542
 
if defined BOOLEAN.SHR
2543
 
 
2544
 
BOOLEAN.SHR.INT:   ld ix, BASIC_DAC+2          ; shift DAC integer to right (bits 15...0-->)
2545
 
                   ld a, (BASIC_ARG+2)         ;
2546
 
                   or a                        ; clear carry
2547
 
                   jp z, MATH.PARM.PUSH        ; return if not shift
2548
 
                   ld b, a                     ; shift count
2549
 
BOOLEAN.SHR.INT.N: rr (ix+1)                   ;
2550
 
                   rr (ix)                     ;
2551
 
                   or a                        ; clear carry
2552
 
                   djnz BOOLEAN.SHR.INT.N      ; next shift
2553
 
                   ld a, 2                     ;
2554
 
                   jp MATH.PARM.PUSH           ; return DAC
2555
 
 
2556
 
endif
2557
 
 
2558
 
if defined BOOLEAN.SHL
2559
 
 
2560
 
BOOLEAN.SHL.INT:   ld ix, BASIC_DAC+2          ; shift DAC integer to left (<--bits 15...0)
2561
 
                   ld a, (BASIC_ARG+2)         ;
2562
 
                   or a                        ; clear carry
2563
 
                   jp z, MATH.PARM.PUSH        ; return if not shift
2564
 
                   ld b, a                     ; shift count
2565
 
BOOLEAN.SHL.INT.N: rl (ix)                     ;
2566
 
                   rl (ix+1)                   ;
2567
 
                   or a                        ; clear carry
2568
 
                   djnz BOOLEAN.SHL.INT.N      ; next shift
2569
 
                   ld a, 2                     ;
2570
 
                   jp MATH.PARM.PUSH           ; return DAC
2571
 
 
2572
 
endif
2573
 
 
2574
 
if defined BOOLEAN.NOT
2575
 
 
2576
 
BOOLEAN.NOT.INT:   ld a, (BASIC_DAC+2)         ;
2577
 
                   cpl                         ;
2578
 
                   ld (BASIC_DAC+2), a         ;
2579
 
                   ld a, (BASIC_DAC+3)         ;
2580
 
                   cpl                         ;
2581
 
                   ld (BASIC_DAC+3), a         ;
2582
 
                   ld a, 2                     ;
2583
 
                   jp MATH.PARM.PUSH           ;
2584
 
 
2585
 
endif
2586
 
 
2587
 
 
2588
 
 
2589
 
;---------------------------------------------------------------------------------------------------------
2590
 
; MEMORY ALLOCATION ROUTINES
2591
 
;---------------------------------------------------------------------------------------------------------
2592
 
; Adapted from memory allocator code by SamSaga2, Spain, 2015
2593
 
; https://www.msx.org/forum/msx-talk/development/asm-memory-allocator
2594
 
; https://www.msx.org/users/samsaga2
2595
 
;---------------------------------------------------------------------------------------------------------
2596
 
memory.heap_start: equ VAR_STACK.END + 1    ; start at end of variable stack
2597
 
memory.heap_end:   equ 0xF0A0 - 100         ; end at start of work area for stack (100 bytes reserved), BIOS and BASIC interpreter
2598
 
block.next:        equ 0                    ; next free block address
2599
 
block.size:        equ 2                    ; size of block including header
2600
 
block:             equ 4                    ; block.next + block.size
2601
 
 
2602
 
;; init
2603
 
memory.init:
2604
 
       ld ix,memory.heap_start              ; first block
2605
 
       ld hl,memory.heap_start+block        ; second block
2606
 
       ;; first block NEXT=secondblock, SIZE=0
2607
 
       ;; with this block we have a fixed start location
2608
 
       ;; because never will be allocated
2609
 
       ld (ix+block.next),l
2610
 
       ld (ix+block.next+1),h
2611
 
       ld (ix+block.size),0
2612
 
       ld (ix+block.size+1),0
2613
 
       ;; second block NEXT=0, SIZE=all
2614
 
       ;; the first and only free block have all available memory
2615
 
       ld (ix+block.next+block),0
2616
 
       ld (ix+block.next+block+1),0
2617
 
       xor a
2618
 
       ;ld hl,memory.heap_end          ; size = @heap_end (stack) - heap_start - block_header * 2 - 100 (buffer for stack)
2619
 
           ld (BIOS_TEMP), sp
2620
 
           ld hl, (BIOS_TEMP)
2621
 
       ld de, memory.heap_start + (block * 2) + 100
2622
 
       sbc hl,de
2623
 
           ;ld de, block * 2 + 100
2624
 
           ;sbc hl, de
2625
 
       ld (ix+block.size+block),l
2626
 
       ld (ix+block.size+block+1),h
2627
 
       ret
2628
 
 
2629
 
;; alloc
2630
 
;; IN BC=size, OUT IX=memptr, NZ=ok
2631
 
memory.alloc:
2632
 
       ld hl,block
2633
 
       add hl,bc
2634
 
       ;push hl
2635
 
       ;pop bc
2636
 
           ld b, h
2637
 
           ld c, l
2638
 
       ld ix,memory.heap_start       ; this
2639
 
       ld iy,0                       ; prev
2640
 
memory.alloc.find:
2641
 
       ld l,(ix+block.size)
2642
 
       ld h,(ix+block.size+1)
2643
 
       xor a
2644
 
       sbc hl,bc
2645
 
       jp z, memory.alloc.exactfit
2646
 
       jp c, memory.alloc.nextblock
2647
 
;; split found block
2648
 
memory.alloc.splitfit:
2649
 
       ;; free space must allow at least two blocks headers (current + next)
2650
 
           or h
2651
 
           jr nz, memory.alloc.splitfit.do   ; if free space > 0xFF, do split
2652
 
             ld a, l
2653
 
             cp 4
2654
 
             jr c, memory.alloc.nextblock    ; if free space < 4, skip to next block
2655
 
memory.alloc.splitfit.do:
2656
 
       ;; newfreeblock = this + BC
2657
 
       push ix
2658
 
       pop hl
2659
 
       add hl,bc
2660
 
       ;; prevblock->next = newfreeblock
2661
 
       ld (iy+block.next),l
2662
 
       ld (iy+block.next+1),h
2663
 
       ;; newfreeblock->next = this->next
2664
 
       push hl
2665
 
       pop iy                        ; iy = newfreeblock
2666
 
       ld l,(ix+block.next)
2667
 
       ld h,(ix+block.next+1)
2668
 
       ld (iy+block.next),l
2669
 
       ld (iy+block.next+1),h
2670
 
       ;; newfreeblock->size = this->size - BC
2671
 
       ld l,(ix+block.size)
2672
 
       ld h,(ix+block.size+1)
2673
 
       xor a
2674
 
       sbc hl,bc
2675
 
       ld (iy+block.size),l
2676
 
       ld (iy+block.size+1),h
2677
 
       ;; this->size = BC
2678
 
       ld (ix+block.size),c
2679
 
       ld (ix+block.size+1),b
2680
 
       jr memory.alloc.ok
2681
 
;; use whole found block
2682
 
memory.alloc.exactfit:
2683
 
       ;; prevblock->next = this->next - remove block from free list
2684
 
       ld l,(ix+block.next)
2685
 
       ld h,(ix+block.next+1)
2686
 
       ld (iy+block.next),l
2687
 
       ld (iy+block.next+1),h
2688
 
memory.alloc.ok:
2689
 
       ;; ix = first byte
2690
 
       ld de,block
2691
 
       add ix,de
2692
 
       ;; enable z-flag
2693
 
       ld a,1
2694
 
       or a
2695
 
       ret
2696
 
memory.alloc.nextblock:
2697
 
       ld l,(ix+block.next)
2698
 
       ld h,(ix+block.next+1)
2699
 
       ld a,l
2700
 
       cp h
2701
 
       ret z
2702
 
         ;; prevblock = this
2703
 
         push ix
2704
 
         pop iy
2705
 
         ;; this = this->next
2706
 
         push hl
2707
 
         pop ix
2708
 
         jp memory.alloc.find
2709
 
 
2710
 
;; free
2711
 
;; IN IX=memptr
2712
 
memory.free:
2713
 
       ;; HL = IX - block_header_size
2714
 
       push ix
2715
 
       pop hl
2716
 
       ld de, block
2717
 
           xor a
2718
 
       sbc hl,de
2719
 
       ;; start of search
2720
 
       ld ix,memory.heap_start
2721
 
memory.free.find:
2722
 
       ld e,(ix+block.next)
2723
 
       ld d,(ix+block.next+1)
2724
 
       ld a,d
2725
 
       or e
2726
 
       jp z, memory.free.passedend
2727
 
         sbc hl,de                     ; test this (HL) against next (DE)
2728
 
         jr c, memory.free.found       ; if DE > HL
2729
 
           add hl,de                     ; restore hl value
2730
 
               push de
2731
 
               pop ix                        ; current = next
2732
 
           jr memory.free.find
2733
 
 
2734
 
;; ix=prev, hl=this, de=next
2735
 
memory.free.found:
2736
 
       add hl,de                     ; restore hl value
2737
 
           ld (ix+block.next), l
2738
 
           ld (ix+block.next+1), h       ; prev->next = this
2739
 
           push hl
2740
 
           pop iy
2741
 
           ld (iy+block.next), e
2742
 
           ld (iy+block.next+1), d       ; this->next = next
2743
 
           push ix                                           ; prev x this
2744
 
           pop iy
2745
 
           push hl
2746
 
           pop ix
2747
 
           push de
2748
 
             call memory.free.coalesce
2749
 
           pop ix                        ; this x next
2750
 
       jr memory.free.coalesce
2751
 
 
2752
 
;; parm1 = *next
2753
 
;; parm2 = *this
2754
 
memory.free.coalesce:
2755
 
           ld c, (iy+block.size)
2756
 
           ld b, (iy+block.size+1)  ; bc = this->size
2757
 
       push iy
2758
 
           pop hl
2759
 
           xor a
2760
 
           adc hl, bc     ; hl = this + this->size
2761
 
           push ix
2762
 
           pop de
2763
 
           xor a
2764
 
           sbc hl, de     ; if this + this->size == next, then this->size += next->size, this->next = next->next
2765
 
           jr z, memory.free.coalesce.do
2766
 
             push ix                ; else, new *this = *next
2767
 
         pop iy
2768
 
                 ret
2769
 
memory.free.coalesce.do:
2770
 
       ld l, (ix+block.size)
2771
 
           ld h, (ix+block.size+1)  ; hl = next->size
2772
 
           xor a
2773
 
           adc hl, bc               ; hl += this->size
2774
 
           ld (iy+block.size), l
2775
 
           ld (iy+block.size+1), h  ; this->size = hl
2776
 
           ld l, (ix+block.next)
2777
 
           ld h, (ix+block.next+1)  ; hl = next->next
2778
 
       ld (iy+block.next), l
2779
 
           ld (iy+block.next+1), h  ; this->next = hl
2780
 
           ret
2781
 
 
2782
 
memory.free.passedend:
2783
 
       ;; append block at the end of the free list
2784
 
       ld (ix+block.next),l
2785
 
       ld (ix+block.next+1),h
2786
 
       push hl
2787
 
       pop iy
2788
 
       ld (iy+block.next),0
2789
 
       ld (iy+block.next+1),0
2790
 
           ret
2791
 
 
2792
 
;; get_free
2793
 
;; OUT BC=freespace
2794
 
memory.get_free:
2795
 
       ld ix,memory.heap_start
2796
 
       ld bc,0
2797
 
memory.get_free.count:
2798
 
       ld a,c
2799
 
       add a,(ix+block.size)
2800
 
       ld c,a
2801
 
       ld a,b
2802
 
       adc a,(ix+block.size+1)
2803
 
       ld b,a
2804
 
       ld l,(ix+block.next)
2805
 
       ld h,(ix+block.next+1)
2806
 
       ld a,h
2807
 
       or l
2808
 
       ret z
2809
 
       push hl
2810
 
       pop ix
2811
 
       jr memory.get_free.count
2812
 
 
2813
 
memory.error:  ld e, 7                           ; out of memory
2814
 
               __call_basic BASIC_ERROR_HANDLER  ;
2815
 
               ret
2816
 
 
2817
 
 
2818
 
 
2819
 
;---------------------------------------------------------------------------------------------------------
2820
 
; GRAPHICS LIBRARY
2821
 
; By: Amaury Carvalho, 2019
2822
 
;---------------------------------------------------------------------------------------------------------
2823
 
; References:
2824
 
; https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm#Algorithm_for_integer_arithmetic
2825
 
; https://en.wikipedia.org/wiki/Midpoint_circle_algorithm
2826
 
; https://rosettacode.org/wiki/Bitmap/Midpoint_circle_algorithm#C
2827
 
; https://www.msx.org/wiki/MSX-BASIC_Instructions
2828
 
;---------------------------------------------------------------------------------------------------------
2829
 
 
2830
 
;---------------------------------------------------------------------------------------------------------
2831
 
; Bios functions
2832
 
;---------------------------------------------------------------------------------------------------------
2833
 
 
2834
 
BIOS_WRTVDP:  EQU 0x0047
2835
 
BIOS_RDVRM:   EQU 0x004A
2836
 
BIOS_WRTVRM:  EQU 0x004D
2837
 
BIOS_LDIRVM:  EQU 0x005C
2838
 
BIOS_LDIRMV:  EQU 0x0059
2839
 
BIOS_PNTINI:  EQU 0x18CF
2840
 
BIOS_RIGHTC:  EQU 0x16C5 ; Move current pixel physical address right
2841
 
BIOS_TRIGHTC: EQU 0x16AC ; Test then RIGHTC if legal
2842
 
BIOS_LEFTC:   EQU 0x16EE ; Move current pixel physical address left
2843
 
BIOS_TLEFTC:  EQU 0x16D8 ; Test then LEFTC if legal
2844
 
BIOS_UPC:     EQU 0x175D ; Move current pixel physical address up
2845
 
BIOS_TUPC:    EQU 0x173C ; Test then UPC if legal
2846
 
BIOS_DOWNC:   EQU 0x172A ; Move current pixel physical address down
2847
 
BIOS_TDOWNC:  EQU 0x170A ; Test then DOWNC if legal
2848
 
BIOS_DCOMPR:  EQU 0x146A ; compare HL and DE (Flag NC if HL>DE, Flag Z if HL=DE, Flag C if HL<DE)
2849
 
BIOS_FILVRM:  EQU 0x0056 ; fill VRAM with value
2850
 
 
2851
 
BIOS_BIGFIL:  EQU 0x016B ; msx 2
2852
 
BIOS_NRDVRM:  EQU 0x0174 ; msx 2
2853
 
BIOS_NWRVRM:  EQU 0x0177 ; msx 2
2854
 
BIOS_NRDVDP:  EQU 0x013E ; msx 2
2855
 
BIOS_VDPSTA:  EQU 0x0131 ; msx 2
2856
 
BIOS_NWRVDP:  EQU 0x012D ; msx 2 (0x0647)
2857
 
 
2858
 
BASIC_SUB_LINE:           equ 0x58fc
2859
 
BASIC_SUB_LINEBOX:        equ 0x5912
2860
 
BASIC_SUB_LINEBOXFILLED:  equ 0x58C1
2861
 
BASIC_SUB_CIRCLE:         equ 0x5B19
2862
 
BASIC_SUB_PAINT1:         equ 0x59DA   ;0x59C8
2863
 
BASIC_SUB_PAINT2:         equ 0x0069   ;0x2664   ;0x2651+3
2864
 
 
2865
 
;---------------------------------------------------------------------------------------------------------
2866
 
; Work areas
2867
 
;---------------------------------------------------------------------------------------------------------
2868
 
 
2869
 
BIOS_RG0SAV: EQU 0xF3DF
2870
 
BIOS_RG1SAV: EQU 0xF3E0
2871
 
BIOS_RG8SAV: EQU 0xFFE7
2872
 
BIOS_BDRATR: EQU 0xFCB2
2873
 
BIOS_STATFL: EQU 0xF3E7  ; VDP status register
2874
 
 
2875
 
BIOS_CXOFF:  EQU 0xF945
2876
 
BIOS_CYOFF:  EQU 0xF947
2877
 
BIOS_GXPOS:  EQU 0xFCB3
2878
 
BIOS_GYPOS:  EQU 0xFCB5
2879
 
 
2880
 
BIOS_GRPNAM: EQU 0xF3C7  ; pattern name table
2881
 
BIOS_GRPCOL: EQU 0xF3C9  ; colour table
2882
 
BIOS_GRPCGP: EQU 0xF3CB  ; pattern generator table
2883
 
BIOS_GRPATR: EQU 0xF3CD  ; sprite attribute table
2884
 
BIOS_GRPPAT: EQU 0xF3CF  ; sprite generator table
2885
 
BIOS_CGPNT:  EQU 0xF920  ; 2 - current MSX Font location (0x1BBF)
2886
 
BIOS_ATRBAS: EQU 0xF928  ; sprite attribute table
2887
 
 
2888
 
BIOS_MLTNAM: EQU 0xF3D1  ; pattern name table (screen 3, multicolor)
2889
 
BIOS_MLTCOL: EQU 0xF3D3  ; colour table (screen 3, multicolor)
2890
 
BIOS_MLTCGP: EQU 0xF3D5  ; pattern generator table (screen 3, multicolor)
2891
 
BIOS_MLTATR: EQU 0xF3D7  ; sprite attribute table (screen 3, multicolor)
2892
 
BIOS_MLTPAT: EQU 0xF3D9  ; sprite generator table (screen 3, multicolor)
2893
 
 
2894
 
BIOS_ASPECT:       equ 0xF931   ;2      Aspect ratio of the circle; set by <ratio> of CIRCLE.
2895
 
BIOS_CENCNT:       equ 0xF933   ;2  Counter used by CIRCLE.
2896
 
BIOS_CLINEF:       equ 0xF935   ;1      Flag to draw line to centre, Used set by CIRCLE
2897
 
BIOS_CNPNTS:       equ 0xF936   ;2      Point to be plottted in a 45° segment, Used set by CIRCLE
2898
 
BIOS_CPLOTF:       equ 0xF938   ;1      Plot polarity flag, Used set by CIRCLE
2899
 
BIOS_CPCNT:        equ 0xF939   ;2      Number of points in 1/8 of circle, Used set by CIRCLE.
2900
 
BIOS_CPCNT8:       equ 0xF93B   ;2      Number of points in the circle. Used by CIRCLE.
2901
 
BIOS_CRCSUM:       equ 0xF93D   ;2      Cyclic redundancy check sum of the circle. Used by CIRCLE.
2902
 
BIOS_CSTCNT:       equ 0xF93F   ;2      Variable to maintain the number of points of the starting angle. Used by the instruction CIRCLE
2903
 
BIOS_CSCLXY:       equ 0xF941   ;1      Scale of X & Y. Used by the instruction CIRCLE
2904
 
BIOS_ASPCT1:       equ 0xF40B   ;2      256/aspect ratio for Basic instruction CIRCLE.
2905
 
BIOS_ASPCT2:       equ 0xF40D   ;2      256*aspect ratio for Basic instruction CIRCLE.
2906
 
BIOS_MAXUPD:       equ 0xF3EC   ;3      Work area used by the instruction CIRCLE, contains JP 0000h at start.
2907
 
BIOS_MINUPD:       equ 0xF3EF   ;3      Work area used by the instruction CIRCLE, contains JP 0000h at start.
2908
 
 
2909
 
BIOS_PARM1:  EQU 0xF6E8 ; 100
2910
 
BIOS_PARM2:  EQU 0xF750 ; 100
2911
 
 
2912
 
GFX_TEMP:   EQU BIOS_PARM1     ; 2
2913
 
GFX_TEMP1:  EQU GFX_TEMP  + 2  ; 2
2914
 
GFX_TEMP2:  EQU GFX_TEMP1 + 2  ; 2
2915
 
GFX_TEMP3:  EQU GFX_TEMP2 + 2  ; 2
2916
 
GFX_TEMP4:  EQU GFX_TEMP3 + 2  ; 2
2917
 
GFX_TEMP5:  EQU GFX_TEMP4 + 2  ; 2
2918
 
GFX_TEMP6:  EQU GFX_TEMP5 + 2  ; 2
2919
 
GFX_TEMP7:  EQU GFX_TEMP6 + 2  ; 2
2920
 
GFX_TEMP8:  EQU GFX_TEMP7 + 2  ; 2
2921
 
GFX_TEMP9:  EQU GFX_TEMP8 + 2  ; 2
2922
 
 
2923
 
GFX_MAX_X:           EQU 0xFCA4  ; 1 (CASSETE LOWLIM)
2924
 
GFX_MAX_Y:           EQU 0xFCA5  ; 1 (CASSETE WINWID)
2925
 
 
2926
 
GFX_SPRITE_FLAGS:        EQU 0xF40A  ; 1 (CASSETE HEADER) - bits 0=check screen limits, 1=check walls, 2=check hotspots,
2927
 
                                     ;                           3=limit touched, 4=wall touched, 5=hotspot touched, 6=collided
2928
 
GFX_SPRITE_SIZE_DAT:     EQU 0xF3FC  ; 1 (CASSETE CS1200)
2929
 
GFX_SPRITE_SIZE_SCR:     EQU 0xF3FD  ; 1
2930
 
GFX_SPRITE_WALLS:        EQU 0xF406  ; 2 (CASSETE LOW)
2931
 
GFX_SPRITE_HOTSPOTS:     EQU 0xF408  ; 2 (CASSETE HIGH)
2932
 
GFX_SPRITE_HOTSPOT_TILE: EQU 0xF405  ; 1 (CASSETE CS2400)
2933
 
GFX_SPRITE_COLLIDER:     EQU 0xF400  ; 1 (CASSETE CS1200)
2934
 
GFX_SPRITE_COLLISION:    EQU 0xF7B5  ; 2 (ARYTA2)
2935
 
 
2936
 
GFX_MUSIC_START:         EQU 0xF401  ; 2 (CASSETE CS2400)
2937
 
GFX_MUSIC_NEXT:          EQU 0xF403  ; 2
2938
 
GFX_MUSIC_PREV:          EQU 0xF74C  ; 2 (PRMPRV)
2939
 
 
2940
 
GFX_TEMP10:              EQU 0xF3FE  ; 2 (CASSETE CS1200)
2941
 
 
2942
 
;BIOS_SCR_SIZE_X: dw 240, 256, 256, 64, 256, 256, 512, 512, 256, 512, 256, 256, 256
2943
 
;BIOS_SCR_SIZE_Y: dw 192, 192, 192, 48, 192, 212, 212, 212, 212, 384, 212, 212, 212
2944
 
BIOS_SCR_SIZE_X: db 239, 255, 255, 63, 255, 255, 255, 255, 255, 255, 255, 255, 255
2945
 
BIOS_SCR_SIZE_Y: db 191, 191, 191, 47, 191, 211, 211, 211, 211, 255, 211, 211, 211
2946
 
 
2947
 
 
2948
 
;---------------------------------------------------------------------------------------------------------
2949
 
; gfxIsScreenModeMSX2
2950
 
; return if screen mode is from MSX 2
2951
 
; out C is set, if MSX2 and screen mode above 3
2952
 
;---------------------------------------------------------------------------------------------------------
2953
 
 
2954
 
gfxIsScreenModeMSX2:
2955
 
  ld a, (BIOS_VERSION)
2956
 
  or 0
2957
 
  jp nz, BIOS_CHKNEW  ; if not MSX1, jump to CHKNEW
2958
 
  scf
2959
 
  ret
2960
 
 
2961
 
;---------------------------------------------------------------------------------------------------------
2962
 
; gfxSetScreenMode
2963
 
; set current screen mode
2964
 
; in A = screen number
2965
 
;---------------------------------------------------------------------------------------------------------
2966
 
 
2967
 
gfxSetScreenMode:
2968
 
  push af
2969
 
    call gfxInitScreenWorkspace
2970
 
    xor a
2971
 
    ld a, (BIOS_VERSION)
2972
 
    or 0
2973
 
    jr nz, gfxSetScreenMode.1  ; if not MSX1, jump
2974
 
  pop af
2975
 
  cp 4
2976
 
  call nc, gfxSetScreenMode.0  ; if screen mode >= 4, change to screen 2
2977
 
  __call_bios BIOS_CHGMOD      ; change the screen mode (msx1)
2978
 
  jr gfxSetScreenMode.2
2979
 
 
2980
 
gfxSetScreenMode.0:
2981
 
  ld a, 2
2982
 
  ret
2983
 
 
2984
 
gfxSetScreenMode.1:
2985
 
  pop af
2986
 
  ld ix, BIOS_CHGMOD2          ; change the screen mode (msx2)
2987
 
  call BIOS_EXTROM
2988
 
 
2989
 
gfxSetScreenMode.2:
2990
 
  call gfxGetScreenHeight
2991
 
  call gfxGetScreenWidth
2992
 
  call gfxGetSpriteSize
2993
 
  jp gfxFillSpriteCollisionTable
2994
 
 
2995
 
gfxInitScreenWorkspace:
2996
 
  ld a, 1
2997
 
  ld (GFX_SPRITE_FLAGS), a     ; bits 0=chk limits, 1=chk walls, 2=chk hotspots, 3=limit touched, 4=wall touched, 5=hotspot touched, 6=collided
2998
 
  xor a
2999
 
  ld (GFX_SPRITE_WALLS), a
3000
 
  ld (GFX_SPRITE_WALLS+1), a
3001
 
  ld (GFX_SPRITE_HOTSPOTS), a
3002
 
  ld (GFX_SPRITE_HOTSPOTS+1), a
3003
 
  ld (GFX_MUSIC_START), a
3004
 
  ld (GFX_MUSIC_START+1), a
3005
 
  ld (GFX_MUSIC_NEXT), a
3006
 
  ld (GFX_MUSIC_NEXT+1), a
3007
 
  ld (GFX_MUSIC_PREV), a
3008
 
  ld (GFX_MUSIC_PREV+1), a
3009
 
  ld (GFX_SPRITE_HOTSPOT_TILE), a
3010
 
  ld (GFX_SPRITE_COLLIDER), a
3011
 
  ret
3012
 
 
3013
 
;---------------------------------------------------------------------------------------------------------
3014
 
; gfxGetScreenMode
3015
 
; return current screen mode
3016
 
; out A = screen number (0=40x24 Text Mode, 1=32x24 Text Mode, 2=Graphics Mode, 3=Multicolour Mode)
3017
 
;---------------------------------------------------------------------------------------------------------
3018
 
 
3019
 
gfxGetScreenMode:
3020
 
  ld a, (BIOS_SCRMOD)
3021
 
  ret
3022
 
 
3023
 
;---------------------------------------------------------------------------------------------------------
3024
 
; gfxSetXY
3025
 
; set current screen location
3026
 
; in BC = x
3027
 
;    DE = y
3028
 
;---------------------------------------------------------------------------------------------------------
3029
 
 
3030
 
gfxSetXY:
3031
 
  ld (BIOS_GRPACX), bc    ; x
3032
 
  ;ld (BIOS_GXPOS), bc
3033
 
  ld (BIOS_GRPACY), de    ; y
3034
 
  ;ld (BIOS_GYPOS), de
3035
 
  jr gfxRefreshXY.1
3036
 
 
3037
 
;---------------------------------------------------------------------------------------------------------
3038
 
; gfxRefreshXY
3039
 
; refresh current screen location
3040
 
;---------------------------------------------------------------------------------------------------------
3041
 
 
3042
 
gfxRefreshXY:
3043
 
  ld bc, (BIOS_GRPACX)    ; x
3044
 
  ld de, (BIOS_GRPACY)    ; y
3045
 
gfxRefreshXY.1:
3046
 
  call gfxIsScreenModeMSX2
3047
 
  jr nc, gfxRefreshXY.2  ; if MSX2 and screen mode above 3
3048
 
    __call_bios BIOS_SCALXY ; BC = X, DE = Y
3049
 
    __call_bios BIOS_MAPXYC ; in BC = X, DE = Y
3050
 
        ret
3051
 
gfxRefreshXY.2:
3052
 
  ld ix, BIOS_SCALXY2 ; BC = X, DE = Y
3053
 
  call BIOS_EXTROM
3054
 
  ld ix, BIOS_MAPXYC2 ; in BC = X, DE = Y
3055
 
  jp BIOS_EXTROM
3056
 
 
3057
 
;---------------------------------------------------------------------------------------------------------
3058
 
; gfxGetXY
3059
 
; get current screen location
3060
 
; out BC = x
3061
 
;     DE = y
3062
 
;---------------------------------------------------------------------------------------------------------
3063
 
 
3064
 
gfxGetXY:
3065
 
  ld bc, (BIOS_GRPACX)    ; x
3066
 
  ld de, (BIOS_GRPACY)    ; y
3067
 
  ret
3068
 
 
3069
 
;---------------------------------------------------------------------------------------------------------
3070
 
; gfxGetScreenHeight
3071
 
; get screen height
3072
 
; out a = screen height
3073
 
;---------------------------------------------------------------------------------------------------------
3074
 
 
3075
 
gfxGetScreenHeight:
3076
 
  push hl
3077
 
  push de
3078
 
    ld hl, BIOS_SCR_SIZE_Y
3079
 
    ld a, (BIOS_SCRMOD)
3080
 
    ld d, 0
3081
 
    ld e, a
3082
 
    add hl, de
3083
 
    ld a, (hl)
3084
 
        ld (GFX_MAX_Y), a
3085
 
  pop de
3086
 
  pop hl
3087
 
  ret
3088
 
 
3089
 
;---------------------------------------------------------------------------------------------------------
3090
 
; gfxGetScreenWidth
3091
 
; get screen width
3092
 
; out a = screen height
3093
 
;---------------------------------------------------------------------------------------------------------
3094
 
 
3095
 
gfxGetScreenWidth:
3096
 
  push hl
3097
 
  push de
3098
 
    ld hl, BIOS_SCR_SIZE_X
3099
 
    ld a, (BIOS_SCRMOD)
3100
 
    ld d, 0
3101
 
    ld e, a
3102
 
    add hl, de
3103
 
    ld a, (hl)
3104
 
        ld (GFX_MAX_X), a
3105
 
  pop de
3106
 
  pop hl
3107
 
  ret
3108
 
 
3109
 
;---------------------------------------------------------------------------------------------------------
3110
 
; gfxGetSpriteSize
3111
 
; get sprite data size
3112
 
; out a = sprite data size
3113
 
;---------------------------------------------------------------------------------------------------------
3114
 
 
3115
 
gfxGetSpriteSize:
3116
 
  push bc
3117
 
    ld bc, 0x0808
3118
 
    ld a, (BIOS_RG1SAV)                 ; bit 0 = double size, bit 1 = sprite size (0=8 pixels, 1=16 pixels)
3119
 
    bit 1, a
3120
 
    jr z, gfxGetSpriteSize.1
3121
 
      ld bc, 0x1010
3122
 
 
3123
 
gfxGetSpriteSize.1:
3124
 
    bit 0, a
3125
 
    jr z, gfxGetSpriteSize.2
3126
 
      sll b
3127
 
 
3128
 
gfxGetSpriteSize.2:
3129
 
    ld (GFX_SPRITE_SIZE_DAT), bc
3130
 
    ld a, c
3131
 
  pop bc
3132
 
  ret
3133
 
 
3134
 
 
3135
 
if defined GFX_FAST and defined PAINT
3136
 
 
3137
 
;---------------------------------------------------------------------------------------------------------
3138
 
; gfxUp
3139
 
; move screen current location up
3140
 
; out: carry if off screen
3141
 
;---------------------------------------------------------------------------------------------------------
3142
 
 
3143
 
gfxUp:
3144
 
  push bc
3145
 
    ld hl, 0
3146
 
        ld de, (BIOS_GRPACY)
3147
 
        or a
3148
 
        sbc hl, de
3149
 
        jr z, gfxUp.1
3150
 
    dec de
3151
 
        ld (BIOS_GRPACY), de
3152
 
    call gfxRefreshXY
3153
 
        scf
3154
 
        ccf
3155
 
        jr gfxUp.2
3156
 
gfxUp.1:
3157
 
        scf
3158
 
gfxUp.2:
3159
 
  pop bc
3160
 
  ret
3161
 
 
3162
 
;---------------------------------------------------------------------------------------------------------
3163
 
; gfxDown
3164
 
; move screen current location down
3165
 
; out: carry if off screen
3166
 
;---------------------------------------------------------------------------------------------------------
3167
 
 
3168
 
gfxDown:
3169
 
  push bc
3170
 
    ld a, (GFX_MAX_Y)
3171
 
    ld l, a
3172
 
    ld h, 0
3173
 
        ld de, (BIOS_GRPACY)
3174
 
        or a
3175
 
    sbc hl, de
3176
 
        jr z, gfxDown.1
3177
 
    inc de
3178
 
        ld (BIOS_GRPACY), de
3179
 
    call gfxRefreshXY
3180
 
        scf
3181
 
        ccf
3182
 
        jr gfxDown.2
3183
 
gfxDown.1:
3184
 
        scf
3185
 
gfxDown.2:
3186
 
  pop bc
3187
 
  ret
3188
 
 
3189
 
;---------------------------------------------------------------------------------------------------------
3190
 
; gfxLeft
3191
 
; move screen current location left
3192
 
; out: carry if off screen
3193
 
;---------------------------------------------------------------------------------------------------------
3194
 
 
3195
 
gfxLeft:
3196
 
  push bc
3197
 
    ld hl, 0
3198
 
        ld de, (BIOS_GRPACX)
3199
 
        or a
3200
 
        sbc hl, de
3201
 
        jr z, gfxLeft.1
3202
 
    dec de
3203
 
        ld (BIOS_GRPACX), de
3204
 
    call gfxRefreshXY
3205
 
        scf
3206
 
        ccf
3207
 
        jr gfxLeft.2
3208
 
gfxLeft.1:
3209
 
        scf
3210
 
gfxLeft.2:
3211
 
  pop bc
3212
 
  ret
3213
 
 
3214
 
;---------------------------------------------------------------------------------------------------------
3215
 
; gfxRight
3216
 
; move screen current location right
3217
 
; out: carry if off screen
3218
 
;---------------------------------------------------------------------------------------------------------
3219
 
 
3220
 
gfxRight:
3221
 
  push bc
3222
 
    ld a, (GFX_MAX_X)
3223
 
    ld l, a
3224
 
    ld h, 0
3225
 
        ld de, (BIOS_GRPACX)
3226
 
        or a
3227
 
    sbc hl, de
3228
 
        jr z, gfxRight.1
3229
 
    inc de
3230
 
        ld (BIOS_GRPACX), de
3231
 
    call gfxRefreshXY
3232
 
        scf
3233
 
        ccf
3234
 
        jr gfxRight.2
3235
 
gfxRight.1:
3236
 
        scf
3237
 
gfxRight.2:
3238
 
  pop bc
3239
 
  ret
3240
 
 
3241
 
endif
3242
 
 
3243
 
;---------------------------------------------------------------------------------------------------------
3244
 
; gfxPushXY
3245
 
; push current screen location
3246
 
;---------------------------------------------------------------------------------------------------------
3247
 
 
3248
 
gfxPushXY:
3249
 
  di
3250
 
    pop  ix
3251
 
    ld iy, (BIOS_GRPACX)    ; x
3252
 
    push iy
3253
 
    ld iy, (BIOS_GRPACY)    ; y
3254
 
    push iy
3255
 
    push ix
3256
 
  ei
3257
 
  ret
3258
 
 
3259
 
;---------------------------------------------------------------------------------------------------------
3260
 
; gfxPopXY
3261
 
; pop current screen location
3262
 
; out BC = x
3263
 
;     DE = y
3264
 
;---------------------------------------------------------------------------------------------------------
3265
 
 
3266
 
gfxPopXY:
3267
 
  pop  ix
3268
 
  pop  de     ; y
3269
 
  pop  bc     ; x
3270
 
  push ix
3271
 
  jp gfxSetXY
3272
 
 
3273
 
;---------------------------------------------------------------------------------------------------------
3274
 
; gfxSetForeColor
3275
 
; set current foreground color
3276
 
; A = color
3277
 
;---------------------------------------------------------------------------------------------------------
3278
 
 
3279
 
gfxSetForeColor:
3280
 
  ld (BIOS_FORCLR), a     ; foreground color
3281
 
  ld (BIOS_ATRBYT), a
3282
 
  ret
3283
 
 
3284
 
;---------------------------------------------------------------------------------------------------------
3285
 
; gfxGetForeColor
3286
 
; get current foreground color
3287
 
; out A = color
3288
 
;---------------------------------------------------------------------------------------------------------
3289
 
 
3290
 
gfxGetForeColor:
3291
 
  ld a, (BIOS_FORCLR)     ; foreground color
3292
 
  ret
3293
 
 
3294
 
;---------------------------------------------------------------------------------------------------------
3295
 
; gfxSetBackColor
3296
 
; set current background color
3297
 
; A = color
3298
 
;---------------------------------------------------------------------------------------------------------
3299
 
 
3300
 
gfxSetBackColor:
3301
 
  ld (BIOS_BAKCLR), a     ; foreground color
3302
 
  ret
3303
 
 
3304
 
;---------------------------------------------------------------------------------------------------------
3305
 
; gfxGetBackColor
3306
 
; get current background color
3307
 
; out A = color
3308
 
;---------------------------------------------------------------------------------------------------------
3309
 
 
3310
 
gfxGetBackColor:
3311
 
  ld a, (BIOS_BAKCLR)     ; foreground color
3312
 
  ret
3313
 
 
3314
 
;---------------------------------------------------------------------------------------------------------
3315
 
; gfxSetBorderColor
3316
 
; set current border color
3317
 
; A = color
3318
 
;---------------------------------------------------------------------------------------------------------
3319
 
 
3320
 
gfxSetBorderColor:
3321
 
  ld (BIOS_BDRCLR), a     ; border color
3322
 
  ret
3323
 
 
3324
 
;---------------------------------------------------------------------------------------------------------
3325
 
; gfxGetBorderColor
3326
 
; get current border color
3327
 
; out A = color
3328
 
;---------------------------------------------------------------------------------------------------------
3329
 
 
3330
 
gfxGetBorderColor:
3331
 
  ld a, (BIOS_BDRCLR)     ; border color
3332
 
  ret
3333
 
 
3334
 
;---------------------------------------------------------------------------------------------------------
3335
 
; gfxSetBorderFill
3336
 
; set fill border color
3337
 
; A = color
3338
 
;---------------------------------------------------------------------------------------------------------
3339
 
 
3340
 
gfxSetBorderFill:
3341
 
  ld (BIOS_BDRATR), a     ; border color
3342
 
  ret
3343
 
 
3344
 
;---------------------------------------------------------------------------------------------------------
3345
 
; gfxGetBorderFill
3346
 
; get fill border color
3347
 
; out A = color
3348
 
;---------------------------------------------------------------------------------------------------------
3349
 
 
3350
 
gfxGetBorderFill:
3351
 
  ld a, (BIOS_BDRATR)     ; border color
3352
 
  ret
3353
 
 
3354
 
;---------------------------------------------------------------------------------------------------------
3355
 
; gfxSetColor
3356
 
; set current color (foreground, background and border)
3357
 
;---------------------------------------------------------------------------------------------------------
3358
 
 
3359
 
gfxSetColor:
3360
 
  ld a, (BIOS_SCRMOD)
3361
 
  bit 3, a
3362
 
  jp nz, BIOS_CHGCLR2 ; change VDP colors - msx2
3363
 
  bit 2, a
3364
 
  jp nz, BIOS_CHGCLR2 ; change VDP colors - msx2
3365
 
  jp BIOS_CHGCLR      ; change VDP colors
3366
 
  ; __call_bios BIOS_SETATR ; change the pixel color
3367
 
  ;ret
3368
 
 
3369
 
;---------------------------------------------------------------------------------------------------------
3370
 
; gfxSetPixel
3371
 
; set pixel in current position to current foreground color
3372
 
;---------------------------------------------------------------------------------------------------------
3373
 
 
3374
 
gfxSetPixel:
3375
 
  call gfxIsScreenModeMSX2
3376
 
  jr nc, gfxSetPixel.1  ; if MSX2 and screen mode above 3
3377
 
    __call_bios BIOS_SETC
3378
 
        ret
3379
 
gfxSetPixel.1:
3380
 
  ld ix, BIOS_SETC2
3381
 
  jp BIOS_EXTROM
3382
 
 
3383
 
;---------------------------------------------------------------------------------------------------------
3384
 
; gfxGetPixel
3385
 
; get pixel color in current position
3386
 
; out A = pixel color
3387
 
;---------------------------------------------------------------------------------------------------------
3388
 
 
3389
 
gfxGetPixel:
3390
 
  call gfxIsScreenModeMSX2
3391
 
  jr nc, gfxGetPixel.1  ; if MSX2 and screen mode above 3
3392
 
    __call_bios BIOS_READC
3393
 
        ret
3394
 
gfxGetPixel.1:
3395
 
  ld ix, BIOS_READC2
3396
 
  jp BIOS_EXTROM
3397
 
 
3398
 
if defined LINE
3399
 
 
3400
 
;---------------------------------------------------------------------------------------------------------
3401
 
; gfxDrawLine
3402
 
; plot a line from current position to informed destination
3403
 
; in BC = destination x
3404
 
;    DE = destination y
3405
 
; https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm#Algorithm_for_integer_arithmetic
3406
 
; https://rosettacode.org/wiki/Bitmap/Bresenham%27s_line_algorithm#C
3407
 
;---------------------------------------------------------------------------------------------------------
3408
 
;void line(int x0, int y0, int x1, int y1) {
3409
 
;  int dx = abs(x1-x0), sx = x0<x1 ? 1 : -1;
3410
 
;  int dy = abs(y1-y0), sy = y0<y1 ? 1 : -1;
3411
 
;  int err = (dx>dy ? dx : -dy)/2, e2;
3412
 
;  for(;;){
3413
 
;    setPixel(x0,y0);
3414
 
;    if (x0==x1 && y0==y1) break;
3415
 
;    e2 = err;
3416
 
;    if (e2 >-dx) { err -= dy; x0 += sx; }
3417
 
;    if (e2 < dy) { err += dx; y0 += sy; }
3418
 
;  }
3419
 
;}
3420
 
 
3421
 
gfxDrawLine:
3422
 
if not defined GFX_FAST
3423
 
  ld hl, (BIOS_GRPACX)
3424
 
  ld (BIOS_GXPOS), hl
3425
 
  ld hl, (BIOS_GRPACY)
3426
 
  ld (BIOS_GYPOS), hl
3427
 
  __call_basic BASIC_SUB_LINE
3428
 
  ret
3429
 
 
3430
 
else
3431
 
 
3432
 
  ld (GFX_TEMP2), bc        ; x
3433
 
  ld (GFX_TEMP3), de        ; y
3434
 
 
3435
 
  ld hl, (BIOS_GRPACX)      ; x0
3436
 
  ld de, (GFX_TEMP2)        ; x
3437
 
  ;or a
3438
 
  ;sbc hl, de
3439
 
  ;jp po, gfxLine.1            ; x0 >= x? else jump to endif
3440
 
  call MATH.COMP.S16
3441
 
  jp c, gfxLine.1             ; x0 < x? jump
3442
 
    or a
3443
 
    sbc hl, de
3444
 
    ld (GFX_TEMP4), hl        ; dx = x0 - x
3445
 
    ld hl, 0xffff
3446
 
    ld (GFX_TEMP5), hl        ; sx = -1
3447
 
    jr gfxLine.2
3448
 
 
3449
 
gfxLine.1:
3450
 
  ld de, (BIOS_GRPACX)      ; x0
3451
 
  ld hl, (GFX_TEMP2)        ; x
3452
 
  or a
3453
 
  sbc hl, de
3454
 
  ld (GFX_TEMP4), hl        ; dx = x - x0
3455
 
  ld hl, 1
3456
 
  ld (GFX_TEMP5), hl        ; sx = 1
3457
 
 
3458
 
gfxLine.2:
3459
 
  ld hl, (BIOS_GRPACY)      ; y0
3460
 
  ld de, (GFX_TEMP3)        ; y
3461
 
  ;or a
3462
 
  ;sbc hl, de
3463
 
  ;jp po, gfxLine.3           ; y0 >= y? else, jump to endif
3464
 
  call MATH.COMP.S16
3465
 
  jp c, gfxLine.3             ; y0 < y? jump
3466
 
    or a
3467
 
    sbc hl, de
3468
 
    ld (GFX_TEMP6), hl        ; dy =  y0 - y
3469
 
    ld hl, 0xffff
3470
 
    ld (GFX_TEMP7), hl        ; sy = -1
3471
 
    jr gfxLine.4
3472
 
 
3473
 
gfxLine.3:
3474
 
  ld de, (BIOS_GRPACY)      ; y0
3475
 
  ld hl, (GFX_TEMP3)        ; y
3476
 
  or a
3477
 
  sbc hl, de
3478
 
  ld (GFX_TEMP6), hl        ; dy = y - y0
3479
 
  ld hl, 1
3480
 
  ld (GFX_TEMP7), hl        ; sy = 1
3481
 
 
3482
 
gfxLine.4:
3483
 
  ld hl, (GFX_TEMP6)       ; dy
3484
 
  ld de, 0
3485
 
  call MATH.COMP.S16
3486
 
  jp z, gfxLine.h          ; dy = 0?
3487
 
 
3488
 
  ld hl, (GFX_TEMP4)       ; dx
3489
 
  ld de, 0
3490
 
  call MATH.COMP.S16
3491
 
  jp z, gfxLine.v          ; dx = 0?
3492
 
 
3493
 
  ld de, (GFX_TEMP4)       ; dx
3494
 
  ld hl, (GFX_TEMP6)       ; dy
3495
 
  or a
3496
 
  adc hl, de
3497
 
  dec hl
3498
 
  dec hl
3499
 
  ld (GFX_TEMP9), hl       ; dxy = dx + dy
3500
 
 
3501
 
  ld de, (GFX_TEMP4)       ; dx
3502
 
  ld hl, (GFX_TEMP6)       ; dy
3503
 
  ;or a
3504
 
  ;sbc hl, de
3505
 
  ;jp pe, gfxLine.5         ; dy < dx? else, jump to endif
3506
 
  call MATH.COMP.S16
3507
 
  jp z, gfxLine.5          ; dy = dx? jump
3508
 
  jp nc, gfxLine.5         ; dy > dx? jump
3509
 
    ;ld hl, 0
3510
 
    ld de, (GFX_TEMP6)     ; dy
3511
 
        or a
3512
 
    srl d
3513
 
    rr e                   ; dy / 2
3514
 
        ;or a
3515
 
        ;sbc hl, de             ; -dy
3516
 
    ld (GFX_TEMP8), de     ; err = -dy / 2
3517
 
    jr gfxLine.loop
3518
 
 
3519
 
gfxLine.5:
3520
 
  ld hl, (GFX_TEMP4)       ; dx
3521
 
  or a
3522
 
  srl h
3523
 
  rr l
3524
 
  ld (GFX_TEMP8), hl       ; err = dx/2
3525
 
 
3526
 
gfxLine.loop:
3527
 
  call gfxSetPixel
3528
 
 
3529
 
  ld hl, (GFX_TEMP9)         ; dxy
3530
 
  ld de, 0
3531
 
  call MATH.COMP.S16
3532
 
  jp nc, gfxLine.loop.0      ; dxy > 0? jump
3533
 
  ;jp z, gfxLine.loop.0      ; dxy = 0? jump
3534
 
 
3535
 
  ret
3536
 
 
3537
 
gfxLine.loop.0:
3538
 
  ld hl, 0
3539
 
  ld de, (GFX_TEMP4)     ; dx
3540
 
  or a
3541
 
  sbc hl, de             ; -dx
3542
 
  ld de, (GFX_TEMP8)     ; e2 = err
3543
 
  push de
3544
 
    ;or a
3545
 
    ;sbc hl, de
3546
 
    ;jp pe, gfxLine.loop.1  ; if -dx < e2, else jump to endif
3547
 
        call MATH.COMP.S16
3548
 
        jp z, gfxLine.loop.1   ; -dx = e2? jump
3549
 
        jp nc, gfxLine.loop.1  ; -dx > e2? jump
3550
 
      ld hl, (GFX_TEMP8)   ; err
3551
 
      ld de, (GFX_TEMP6)   ; dy
3552
 
      or a
3553
 
      sbc hl, de
3554
 
      ld (GFX_TEMP8), hl   ; err -= dy
3555
 
 
3556
 
      ld hl, (GFX_TEMP9)   ; dxy
3557
 
      dec hl
3558
 
      ld (GFX_TEMP9), hl   ; dxy -= 1
3559
 
 
3560
 
      ld hl, (BIOS_GRPACX)
3561
 
      ld de, (GFX_TEMP5)
3562
 
      or a
3563
 
      adc hl, de
3564
 
      ld (BIOS_GRPACX), hl  ; x0 += sx
3565
 
 
3566
 
gfxLine.loop.1:
3567
 
  pop hl                    ; e2
3568
 
  ld de, (GFX_TEMP6)        ; dy
3569
 
  ;or a
3570
 
  ;sbc hl, de
3571
 
  ;jp pe, gfxLine.loop.2     ; if e2 < dy, else jump to endif
3572
 
  call MATH.COMP.S16
3573
 
  jp z, gfxLine.loop.2      ; e2 = dy? jump
3574
 
  jp nc, gfxLine.loop.2     ; e2 > dy? jump
3575
 
    ld hl, (GFX_TEMP8)      ; err
3576
 
    ld de, (GFX_TEMP4)      ; dx
3577
 
    or a
3578
 
    adc hl, de
3579
 
    ld (GFX_TEMP8), hl      ; err += dx
3580
 
 
3581
 
    ld hl, (GFX_TEMP9)      ; dxy
3582
 
    dec hl
3583
 
    ld (GFX_TEMP9), hl      ; dxy -= 1
3584
 
 
3585
 
    ld hl, (BIOS_GRPACY)
3586
 
    ld de, (GFX_TEMP7)
3587
 
    or a
3588
 
    adc hl, de
3589
 
    ld (BIOS_GRPACY), hl    ; y0 += sy
3590
 
 
3591
 
gfxLine.loop.2:
3592
 
  call gfxRefreshXY
3593
 
  jp gfxLine.loop
3594
 
 
3595
 
gfxLine.h:
3596
 
  ld a, (GFX_TEMP5)        ; sx
3597
 
  bit 7, a
3598
 
  jr z, gfxLine.h.1        ; if a is positive
3599
 
    ld hl, (BIOS_GRPACX)
3600
 
    ld de, (GFX_TEMP4)
3601
 
    or a
3602
 
    sbc hl, de
3603
 
    ld (BIOS_GRPACX), hl
3604
 
    call gfxRefreshXY
3605
 
 
3606
 
gfxLine.h.1:
3607
 
  __call_bios BIOS_FETCHC
3608
 
  ld hl, (GFX_TEMP4)       ; dx
3609
 
  inc hl
3610
 
  call gfxDrawHorLine      ; HL = pixel count
3611
 
  ret
3612
 
 
3613
 
gfxLine.v:
3614
 
  ld a, (GFX_TEMP7)        ; sy
3615
 
  bit 7, a
3616
 
  jr z, gfxLine.v.1        ; if a is positive
3617
 
    ld hl, (BIOS_GRPACY)
3618
 
    ld de, (GFX_TEMP6)
3619
 
    or a
3620
 
    sbc hl, de
3621
 
    ld (BIOS_GRPACY), hl
3622
 
    call gfxRefreshXY
3623
 
 
3624
 
gfxLine.v.1:
3625
 
  call gfxSetPixel
3626
 
  ld hl, (GFX_TEMP6)       ; dy
3627
 
  inc hl
3628
 
  ld (GFX_TEMP3), hl
3629
 
  jp gfxBox.drawVerLine
3630
 
endif
3631
 
 
3632
 
endif
3633
 
 
3634
 
if defined BOX or defined FBOX or defined BOX_STEP or defined FBOX_STEP
3635
 
 
3636
 
;---------------------------------------------------------------------------------------------------------
3637
 
; gfxDrawBox
3638
 
; plot a box from current position to informed destination
3639
 
; in BC = destination x
3640
 
;    DE = destination y
3641
 
;    A  = filled flag (0 = not filled, <>0 = filled)
3642
 
;---------------------------------------------------------------------------------------------------------
3643
 
 
3644
 
gfxDrawBox:
3645
 
 
3646
 
if not defined GFX_FAST
3647
 
  ld hl, (BIOS_GRPACX)
3648
 
  ld (BIOS_GXPOS), hl
3649
 
  ld hl, (BIOS_GRPACY)
3650
 
  ld (BIOS_GYPOS), hl
3651
 
  ld hl, BASIC_SUB_LINEBOX
3652
 
  or 0
3653
 
  jr z, gfxDrawBox.1
3654
 
    call gfxIsScreenModeMSX2
3655
 
    jr nc, gfxDrawBox.2
3656
 
    ld hl, BASIC_SUB_LINEBOXFILLED
3657
 
 
3658
 
gfxDrawBox.1:
3659
 
  push hl
3660
 
  pop ix
3661
 
  jp BIOS_CALBAS   ; BIOS_CALSLT
3662
 
 
3663
 
 
3664
 
gfxDrawBox.2:
3665
 
  xor a
3666
 
  ld hl, BASIC_BUF
3667
 
  ld (hl), a
3668
 
  ld ix, BIOS_DOBOXF
3669
 
  jp BIOS_EXTROM
3670
 
 
3671
 
else
3672
 
  call gfxAdjustDestXY
3673
 
  or 0
3674
 
  jr nz, gfxBox.filled
3675
 
 
3676
 
gfxBox.notFilled:
3677
 
  call gfxPushXY
3678
 
    call gfxBox.drawHorLine
3679
 
    ld hl, (GFX_TEMP2)
3680
 
    ld de, (BIOS_GRPACX)
3681
 
    or a
3682
 
    adc hl, de
3683
 
    dec hl
3684
 
    ld (BIOS_GRPACX), hl
3685
 
    call gfxRefreshXY
3686
 
    call gfxBox.drawVerLine
3687
 
  call gfxPopXY
3688
 
  call gfxBox.drawVerLine
3689
 
  call gfxBox.drawHorLine
3690
 
  ret
3691
 
 
3692
 
gfxBox.filled:
3693
 
  ld hl, (GFX_TEMP3)
3694
 
  ;inc hl
3695
 
gfxBox.filled.loop:
3696
 
  push hl
3697
 
    ld bc, (BIOS_GRPACX)
3698
 
        push bc
3699
 
      call gfxBox.drawHorLine
3700
 
        pop bc
3701
 
        ld (BIOS_GRPACX), bc
3702
 
        ld bc, (BIOS_GRPACY)
3703
 
        inc bc
3704
 
        ld (BIOS_GRPACY), bc
3705
 
    call gfxRefreshXY
3706
 
  pop hl
3707
 
  ld de, 1
3708
 
  or a
3709
 
  sbc hl, de
3710
 
  jr nz, gfxBox.filled.loop
3711
 
  ret
3712
 
 
3713
 
gfxBox.drawHorLine:
3714
 
  ld hl, (GFX_TEMP2)
3715
 
  ;inc hl
3716
 
  call gfxDrawHorLine
3717
 
  ret
3718
 
 
3719
 
gfxBox.drawVerLine:
3720
 
  ld hl, (GFX_TEMP3)
3721
 
  dec hl
3722
 
gfxBox.drawVerLine.loop:
3723
 
  push hl
3724
 
    call gfxDown
3725
 
        call gfxSetPixel
3726
 
  pop hl
3727
 
  ld de, 1
3728
 
  or a
3729
 
  sbc hl, de
3730
 
  jr nz, gfxBox.drawVerLine.loop
3731
 
  ret
3732
 
 
3733
 
;---------------------------------------------------------------------------------------------------------
3734
 
; gfxDrawHorLine
3735
 
; draw a horizontal line
3736
 
; HL = pixel count
3737
 
;---------------------------------------------------------------------------------------------------------
3738
 
 
3739
 
gfxDrawHorLine:
3740
 
  ld a, (BIOS_SCRMOD)
3741
 
  cp 5
3742
 
  jr c, gfxDrawHorLine.2 ; if screen mode < 5 then jump
3743
 
    bit 7, h
3744
 
    ret nz               ; return if negative
3745
 
    xor a
3746
 
    cp h
3747
 
    jr nz, gfxDrawHorLine.1
3748
 
    cp l
3749
 
    ret z                ; return if hl = 0
3750
 
    call gfxPushXY
3751
 
gfxDrawHorLine.1:
3752
 
    push hl
3753
 
          call gfxSetPixel
3754
 
      call gfxRight
3755
 
    pop hl
3756
 
    ld de, 1
3757
 
    sbc hl, de
3758
 
    jr nz, gfxDrawHorLine.1
3759
 
    call gfxPopXY
3760
 
    ret
3761
 
gfxDrawHorLine.2:
3762
 
  __call_bios BIOS_NSETCX    ; HL = fill count
3763
 
  ret
3764
 
 
3765
 
;---------------------------------------------------------------------------------------------------------
3766
 
; gfxAdjustDestXY
3767
 
; invert if dest XY is less than current XY position
3768
 
; BC = dest x
3769
 
; DE = dest y
3770
 
;---------------------------------------------------------------------------------------------------------
3771
 
 
3772
 
gfxAdjustDestXY:
3773
 
  push af
3774
 
    ld (GFX_TEMP2), bc        ; x
3775
 
        ld (GFX_TEMP3), de        ; y
3776
 
 
3777
 
    ; verify x againt current position
3778
 
    ld hl, (BIOS_GRPACX)
3779
 
        ld de, (GFX_TEMP2)
3780
 
        and a
3781
 
        sbc hl, de                ; dx = x1 - x0
3782
 
        bit 7, h                  ; result is negative?
3783
 
        jr z, gfxAdjustDestXY.1
3784
 
        add hl, de
3785
 
        ld (BIOS_GRPACX), hl
3786
 
    ex de, hl
3787
 
    or a
3788
 
        sbc hl, de
3789
 
gfxAdjustDestXY.1:
3790
 
    inc hl
3791
 
        ld (GFX_TEMP2), hl
3792
 
 
3793
 
    ; verify y againt current position
3794
 
    ld hl, (BIOS_GRPACY)
3795
 
        ld de, (GFX_TEMP3)
3796
 
        and a
3797
 
        sbc hl, de                ; dy = y1 - y0
3798
 
        bit 7, h                  ; result is negative?
3799
 
        jr z, gfxAdjustDestXY.2
3800
 
        add hl, de
3801
 
        ld (BIOS_GRPACY), hl
3802
 
    ex de, hl
3803
 
    or a
3804
 
        sbc hl, de
3805
 
gfxAdjustDestXY.2:
3806
 
    inc hl
3807
 
        ld (GFX_TEMP3), hl
3808
 
 
3809
 
        ; refresh new position
3810
 
        call gfxRefreshXY
3811
 
  pop af
3812
 
  ret
3813
 
endif
3814
 
 
3815
 
endif
3816
 
 
3817
 
if defined CIRCLE
3818
 
 
3819
 
;---------------------------------------------------------------------------------------------------------
3820
 
; gfxDrawCircle
3821
 
; plot a circle centered in current position
3822
 
; BC = tracing end x
3823
 
; DE = tracing end y
3824
 
; HL = radius
3825
 
; A  = filled flag (0 = not filled, <>0 = filled)
3826
 
; https://en.wikipedia.org/wiki/Midpoint_circle_algorithm
3827
 
; https://rosettacode.org/wiki/Bitmap/Midpoint_circle_algorithm#C
3828
 
;---------------------------------------------------------------------------------------------------------
3829
 
 
3830
 
gfxDrawCircle:
3831
 
 
3832
 
if not defined GFX_FAST
3833
 
  bit 7,h
3834
 
  ret nz                ; return if negative radius
3835
 
  ld (BIOS_GXPOS), hl   ; circle ray
3836
 
  ld de, (BIOS_GXPOS)
3837
 
  ld bc, (BIOS_GRPACY)
3838
 
  ld (BIOS_GYPOS), bc
3839
 
  xor a
3840
 
  ;cp h
3841
 
  ;jr nz, gfxDrawCircle.1
3842
 
  ;cp l
3843
 
  ;ret z
3844
 
gfxDrawCircle.1:
3845
 
  ld hl, BASIC_BUF
3846
 
  ld (hl), a
3847
 
  ld ix, 0xFFFF
3848
 
  __call_basic BASIC_SUB_CIRCLE
3849
 
  ret
3850
 
else
3851
 
  ld (GFX_TEMP),  hl   ; radius
3852
 
  ld de, 0
3853
 
  sbc hl, de
3854
 
  ret z                ; return if zero radius
3855
 
  bit 7,h
3856
 
  ret nz               ; return if negative radius
3857
 
 
3858
 
  call gfxGetXY
3859
 
  ld (GFX_TEMP1), bc   ; x0
3860
 
  ld (GFX_TEMP2), de   ; y0
3861
 
 
3862
 
  or 0
3863
 
  jp nz, gfxCircle.filled
3864
 
 
3865
 
gfxCircle.notFilled:
3866
 
  ld hl, 1
3867
 
  ld de, (GFX_TEMP)    ; radius
3868
 
  or a
3869
 
  sbc hl, de
3870
 
  ld (GFX_TEMP3), hl   ; f = 1 - radius
3871
 
 
3872
 
  ld hl, 0
3873
 
  ld (GFX_TEMP4), hl   ; ddF_x = 0
3874
 
 
3875
 
  ld hl, (GFX_TEMP)
3876
 
  or a
3877
 
  adc hl, hl
3878
 
  ex de, hl
3879
 
  ld hl, 0
3880
 
  or a
3881
 
  sbc hl, de
3882
 
  ld (GFX_TEMP5), hl   ; ddF_y = -2 * radius
3883
 
 
3884
 
  ld hl, 0
3885
 
  ld (GFX_TEMP6), hl   ; x = 0
3886
 
 
3887
 
  ld hl, (GFX_TEMP)
3888
 
  ld (GFX_TEMP7), hl   ; y = radius
3889
 
 
3890
 
  ; plot(x0, y0 + radius)
3891
 
  ld de, (GFX_TEMP)    ; radius
3892
 
  ld hl, (GFX_TEMP2)   ; y0
3893
 
  or a
3894
 
  adc hl, de
3895
 
  ex de, hl
3896
 
  ld bc, (GFX_TEMP1)   ; x0
3897
 
  call gfxSetXY
3898
 
  call gfxSetPixel
3899
 
 
3900
 
  ; plot(x0, y0 - radius)
3901
 
  ld de, (GFX_TEMP)    ; radius
3902
 
  ld hl, (GFX_TEMP2)   ; y0
3903
 
  or a
3904
 
  sbc hl, de
3905
 
  ex de, hl
3906
 
  ld bc, (GFX_TEMP1)   ; x0
3907
 
  call gfxSetXY
3908
 
  call gfxSetPixel
3909
 
 
3910
 
  ; plot(x0 + radius, y0)
3911
 
  ld hl, (GFX_TEMP1)   ; x0
3912
 
  ld de, (GFX_TEMP)    ; radius
3913
 
  or a
3914
 
  adc hl, de
3915
 
  ;push hl
3916
 
  ;pop bc
3917
 
  ld b, h
3918
 
  ld c, l
3919
 
  ld de, (GFX_TEMP2)   ; y0
3920
 
  call gfxSetXY
3921
 
  call gfxSetPixel
3922
 
 
3923
 
  ; plot(x0 - radius, y0)
3924
 
  ld hl, (GFX_TEMP1)   ; x0
3925
 
  ld de, (GFX_TEMP)    ; radius
3926
 
  or a
3927
 
  sbc hl, de
3928
 
  ;push hl
3929
 
  ;pop bc
3930
 
  ld b, h
3931
 
  ld c, l
3932
 
  ld de, (GFX_TEMP2)   ; y0
3933
 
  call gfxSetXY
3934
 
  call gfxSetPixel
3935
 
  jp gfxCircle.notFilled.3
3936
 
 
3937
 
gfxCircle.notFilled.1:
3938
 
  ld hl, (GFX_TEMP3)   ; f
3939
 
  bit 7, h
3940
 
  jr nz, gfxCircle.notFilled.2  ; if( f < 0 ), jump
3941
 
 
3942
 
    ld hl, (GFX_TEMP7)        ; y -= 1
3943
 
    dec hl
3944
 
    ld (GFX_TEMP7), hl
3945
 
 
3946
 
    ld hl, (GFX_TEMP5)        ; ddF_y += 2
3947
 
    inc hl
3948
 
    inc hl
3949
 
    ld (GFX_TEMP5), hl
3950
 
 
3951
 
    ld hl, (GFX_TEMP3)        ; f
3952
 
    ld de, (GFX_TEMP5)        ; ddF_y
3953
 
    or a
3954
 
    adc hl, de
3955
 
    ld (GFX_TEMP3), hl        ; f += ddF_y
3956
 
 
3957
 
gfxCircle.notFilled.2:
3958
 
  ld hl, (GFX_TEMP6)   ; x
3959
 
  inc hl
3960
 
  ld (GFX_TEMP6), hl   ; x++
3961
 
 
3962
 
  ld hl, (GFX_TEMP4)   ; ddF_x += 2
3963
 
  inc hl
3964
 
  inc hl
3965
 
  ld (GFX_TEMP4), hl
3966
 
 
3967
 
  ld hl, (GFX_TEMP3)   ; f
3968
 
  ld de, (GFX_TEMP4)   ; ddF_x
3969
 
  or a
3970
 
  adc hl, de
3971
 
  inc hl
3972
 
  ld (GFX_TEMP3), hl   ; f += ddF_x + 1
3973
 
 
3974
 
  ; plot(x0 + x, y0 + y)
3975
 
  ld hl, (GFX_TEMP1)   ; x0
3976
 
  ld de, (GFX_TEMP6)   ; x
3977
 
  or a
3978
 
  adc hl, de
3979
 
  ;push hl
3980
 
  ;pop bc
3981
 
  ld b, h
3982
 
  ld c, l
3983
 
  ld hl, (GFX_TEMP2)   ; y0
3984
 
  ld de, (GFX_TEMP7)   ; y
3985
 
  or a
3986
 
  adc hl, de
3987
 
  ex de, hl
3988
 
  call gfxSetXY
3989
 
  call gfxSetPixel
3990
 
 
3991
 
  ; plot(x0 - x, y0 + y)
3992
 
  ld hl, (GFX_TEMP1)   ; x0
3993
 
  ld de, (GFX_TEMP6)   ; x
3994
 
  or a
3995
 
  sbc hl, de
3996
 
  ;push hl
3997
 
  ;pop bc
3998
 
  ld b, h
3999
 
  ld c, l
4000
 
  ld hl, (GFX_TEMP2)   ; y0
4001
 
  ld de, (GFX_TEMP7)   ; y
4002
 
  or a
4003
 
  adc hl, de
4004
 
  ex de, hl
4005
 
  call gfxSetXY
4006
 
  call gfxSetPixel
4007
 
 
4008
 
  ; plot(x0 + x, y0 - y)
4009
 
  ld hl, (GFX_TEMP1)   ; x0
4010
 
  ld de, (GFX_TEMP6)   ; x
4011
 
  or a
4012
 
  adc hl, de
4013
 
  ;push hl
4014
 
  ;pop bc
4015
 
  ld b, h
4016
 
  ld c, l
4017
 
  ld hl, (GFX_TEMP2)   ; y0
4018
 
  ld de, (GFX_TEMP7)   ; y
4019
 
  or a
4020
 
  sbc hl, de
4021
 
  ex de, hl
4022
 
  call gfxSetXY
4023
 
  call gfxSetPixel
4024
 
 
4025
 
  ; plot(x0 - x, y0 - y)
4026
 
  ld hl, (GFX_TEMP1)   ; x0
4027
 
  ld de, (GFX_TEMP6)   ; x
4028
 
  or a
4029
 
  sbc hl, de
4030
 
  ;push hl
4031
 
  ;pop bc
4032
 
  ld b, h
4033
 
  ld c, l
4034
 
  ld hl, (GFX_TEMP2)   ; y0
4035
 
  ld de, (GFX_TEMP7)   ; y
4036
 
  or a
4037
 
  sbc hl, de
4038
 
  ex de, hl
4039
 
  call gfxSetXY
4040
 
  call gfxSetPixel
4041
 
 
4042
 
  ; plot(x0 + y, y0 + x)
4043
 
  ld hl, (GFX_TEMP1)   ; x0
4044
 
  ld de, (GFX_TEMP7)   ; y
4045
 
  or a
4046
 
  adc hl, de
4047
 
  ;push hl
4048
 
  ;pop bc
4049
 
  ld b, h
4050
 
  ld c, l
4051
 
  ld hl, (GFX_TEMP2)   ; y0
4052
 
  ld de, (GFX_TEMP6)   ; x
4053
 
  or a
4054
 
  adc hl, de
4055
 
  ex de, hl
4056
 
  call gfxSetXY
4057
 
  call gfxSetPixel
4058
 
 
4059
 
  ; plot(x0 - y, y0 + x)
4060
 
  ld hl, (GFX_TEMP1)   ; x0
4061
 
  ld de, (GFX_TEMP7)   ; y
4062
 
  or a
4063
 
  sbc hl, de
4064
 
  ;push hl
4065
 
  ;pop bc
4066
 
  ld b, h
4067
 
  ld c, l
4068
 
  ld hl, (GFX_TEMP2)   ; y0
4069
 
  ld de, (GFX_TEMP6)   ; x
4070
 
  or a
4071
 
  adc hl, de
4072
 
  ex de, hl
4073
 
  call gfxSetXY
4074
 
  call gfxSetPixel
4075
 
 
4076
 
  ; plot(x0 + y, y0 - x)
4077
 
  ld hl, (GFX_TEMP1)   ; x0
4078
 
  ld de, (GFX_TEMP7)   ; y
4079
 
  or a
4080
 
  adc hl, de
4081
 
  ;push hl
4082
 
  ;pop bc
4083
 
  ld b, h
4084
 
  ld c, l
4085
 
  ld hl, (GFX_TEMP2)   ; y0
4086
 
  ld de, (GFX_TEMP6)   ; x
4087
 
  or a
4088
 
  sbc hl, de
4089
 
  ex de, hl
4090
 
  call gfxSetXY
4091
 
  call gfxSetPixel
4092
 
 
4093
 
  ; plot(x0 - y, y0 - x)
4094
 
  ld hl, (GFX_TEMP1)   ; x0
4095
 
  ld de, (GFX_TEMP7)   ; y
4096
 
  or a
4097
 
  sbc hl, de
4098
 
  ;push hl
4099
 
  ;pop bc
4100
 
  ld b, h
4101
 
  ld c, l
4102
 
  ld hl, (GFX_TEMP2)   ; y0
4103
 
  ld de, (GFX_TEMP6)   ; x
4104
 
  or a
4105
 
  sbc hl, de
4106
 
  ex de, hl
4107
 
  call gfxSetXY
4108
 
  call gfxSetPixel
4109
 
 
4110
 
gfxCircle.notFilled.3:
4111
 
  ld hl, (GFX_TEMP6)           ; x
4112
 
  ld de, (GFX_TEMP7)           ; y
4113
 
  or a
4114
 
  sbc hl, de
4115
 
  jp c, gfxCircle.notFilled.1  ; while( x < y )
4116
 
  ld bc, (GFX_TEMP1)   ; x0
4117
 
  ld de, (GFX_TEMP2)   ; y0
4118
 
  call gfxSetXY
4119
 
  ret
4120
 
 
4121
 
gfxCircle.filled
4122
 
  call gfxCircle.notFilled
4123
 
  ld hl, (BIOS_BDRATR)
4124
 
  push hl
4125
 
        ld hl, (BIOS_FORCLR)
4126
 
        ld (BIOS_BDRATR), hl
4127
 
        ld a, 1
4128
 
        call gfxBorderFill
4129
 
  pop hl
4130
 
  ld (BIOS_BDRATR), hl
4131
 
  ret
4132
 
endif
4133
 
 
4134
 
endif
4135
 
 
4136
 
if defined PAINT or (defined CIRCLE and defined GFX_FAST)
4137
 
 
4138
 
;---------------------------------------------------------------------------------------------------------
4139
 
; gfxBorderFill
4140
 
; Fill current region delimited by border attribute color changing pixels to foreground color
4141
 
; in: a = fill type (0 = not symmetric, 1 = symmetric)
4142
 
;---------------------------------------------------------------------------------------------------------
4143
 
 
4144
 
gfxBorderFill:
4145
 
 
4146
 
if not defined GFX_FAST
4147
 
 
4148
 
  ld bc, (BIOS_GRPACX)
4149
 
  ld (BIOS_GXPOS), bc
4150
 
  ld de, (BIOS_GRPACY)
4151
 
  ld (BIOS_GYPOS), de
4152
 
  push bc
4153
 
  push de
4154
 
 
4155
 
  xor a
4156
 
  ld hl, BASIC_BUF
4157
 
  ld (hl), a
4158
 
 
4159
 
  ld a, (BIOS_BDRATR)
4160
 
  xor b
4161
 
  ld e, a
4162
 
  ld a, (BIOS_ATRBYT)
4163
 
  xor d
4164
 
  ld c, a
4165
 
  ;ld ix, 0xFFFF
4166
 
  ;ld iy, 0xFFFF
4167
 
 
4168
 
  call gfxIsScreenModeMSX2
4169
 
  jr nc, gfxBorderFill.1  ; if MSX2 and screen mode above 3, jump
4170
 
    ld a, (BIOS_BDRATR)
4171
 
    ld (BIOS_ATRBYT), a
4172
 
    ld e, a
4173
 
    __call_basic BASIC_SUB_PAINT1
4174
 
    ret
4175
 
 
4176
 
gfxBorderFill.1:
4177
 
  __call_basic BASIC_SUB_PAINT1
4178
 
  ret
4179
 
  ;ld ix, BASIC_SUB_PAINT2
4180
 
  ;jp BIOS_EXTROM
4181
 
 
4182
 
else
4183
 
 
4184
 
  ld (GFX_TEMP1), a
4185
 
  ld hl, (BIOS_GRPACY)
4186
 
  push hl
4187
 
    call gfxBorderFill.down
4188
 
  pop hl
4189
 
  push hl
4190
 
    ld (BIOS_GRPACY), hl
4191
 
    call gfxRefreshXY
4192
 
    call gfxBorderFill.up
4193
 
  pop hl
4194
 
  ld (BIOS_GRPACY), hl
4195
 
  call gfxRefreshXY
4196
 
  ret
4197
 
 
4198
 
gfxBorderFill.down:
4199
 
  call gfxBorderFill.line
4200
 
  call gfxDown
4201
 
  ret c
4202
 
  call gfxGetPixel
4203
 
  ld hl, BIOS_BDRATR
4204
 
  cp (hl)
4205
 
  jr nz, gfxBorderFill.down
4206
 
  ret
4207
 
 
4208
 
gfxBorderFill.up:
4209
 
  call gfxBorderFill.line
4210
 
  call gfxUp
4211
 
  ret c
4212
 
  call gfxGetPixel
4213
 
  ld hl, BIOS_BDRATR
4214
 
  cp (hl)
4215
 
  jr nz, gfxBorderFill.up
4216
 
  ret
4217
 
 
4218
 
gfxBorderFill.line:
4219
 
  ld de, (BIOS_GRPACX)
4220
 
  push de
4221
 
    ld b, 1    ; fill flag
4222
 
    ld de, 1   ; skip count
4223
 
    __call_bios BIOS_SCANR
4224
 
        ;inc hl
4225
 
        ;ld (GFX_TEMP2), hl        ; pixel count transversed
4226
 
  pop de
4227
 
  push de
4228
 
    ld (BIOS_GRPACX), de
4229
 
    call gfxRefreshXY
4230
 
    ;ld a, (GFX_TEMP1)
4231
 
    ;cp 0                       ; 0 = not symmetric, 1 = symmetric
4232
 
        ;jr z, gfxBorderFill.line.1
4233
 
        ;ld hl, (GFX_TEMP2)
4234
 
        ;__call_bios BIOS_NSETCX    ; HL = fill count
4235
 
        ;jr gfxBorderFill.line.2
4236
 
gfxBorderFill.line.1:
4237
 
    ld b, 1    ; fill flag
4238
 
    ld de, 0   ; skip count
4239
 
    __call_bios BIOS_SCANL
4240
 
gfxBorderFill.line.2:
4241
 
  pop de
4242
 
  ld (BIOS_GRPACX), de
4243
 
  call gfxRefreshXY
4244
 
  ret
4245
 
 
4246
 
;---------------------------------------------------------------------------------------------------------
4247
 
; gfxFloadFill
4248
 
; Fload fill current region changing current pixel color to foreground color
4249
 
; https://en.wikipedia.org/wiki/Flood_fill
4250
 
;---------------------------------------------------------------------------------------------------------
4251
 
 
4252
 
gfxFloadFill:
4253
 
  call gfxGetPixel
4254
 
  ld (GFX_TEMP), a    ; replacement-color
4255
 
  call gfxFloadFill.recursive
4256
 
  ret
4257
 
 
4258
 
gfxFloadFill.recursive:
4259
 
  ; 1. If target-color is equal to replacement-color, return.
4260
 
  ld a, (GFX_TEMP)
4261
 
  ld hl, BIOS_FORCLR
4262
 
  cp (hl)
4263
 
  ret z
4264
 
 
4265
 
  ; 2. ElseIf the color of node is not equal to target-color, return.
4266
 
  call gfxGetPixel
4267
 
  ld hl, GFX_TEMP
4268
 
  cp (hl)
4269
 
  ret nz
4270
 
 
4271
 
  ; 3. Else Set the color of node to replacement-color.
4272
 
  call gfxSetPixel
4273
 
 
4274
 
  ; 4. Perform Flood-fill (one step to the left of node, target-color, replacement-color).
4275
 
gfxFloadFill.recursive.left:
4276
 
  call gfxLeft
4277
 
  jr c, gfxFloadFill.recursive.right
4278
 
    call gfxFloadFill.recursive
4279
 
    call gfxRight
4280
 
 
4281
 
  ;    Perform Flood-fill (one step to the right of node, target-color, replacement-color).
4282
 
gfxFloadFill.recursive.right:
4283
 
  call gfxRight
4284
 
  jr c, gfxFloadFill.recursive.up
4285
 
    call gfxFloadFill.recursive
4286
 
    call gfxLeft
4287
 
 
4288
 
  ;    Perform Flood-fill (one step to the up of node, target-color, replacement-color).
4289
 
gfxFloadFill.recursive.up:
4290
 
  call gfxUp
4291
 
  jr c, gfxFloadFill.recursive.down
4292
 
    call gfxFloadFill.recursive
4293
 
    call gfxDown
4294
 
 
4295
 
  ;    Perform Flood-fill (one step to the down of node, target-color, replacement-color).
4296
 
gfxFloadFill.recursive.down:
4297
 
  call gfxDown
4298
 
  ret c
4299
 
    call gfxFloadFill.recursive
4300
 
    call gfxUp
4301
 
  ret
4302
 
 
4303
 
endif
4304
 
 
4305
 
endif
4306
 
 
4307
 
if defined SPRITEMODE
4308
 
 
4309
 
;---------------------------------------------------------------------------------------------------------
4310
 
; gfxSetSpriteMode
4311
 
; set current sprite mode
4312
 
; A = sprite mode
4313
 
;     0: Spritesize is 8 by 8 pixels - default value
4314
 
;     1: Spritesize is 8 by 8 pixels, magnified to 16 by 16 pixels
4315
 
;     2: Spritesize is 16 by 16 pixels
4316
 
;     3: Spritesize is 16 by 16 pixels, magnified to 32 by 32 pixels
4317
 
; RG1SAV bit 0 = magnify sprite (double size)
4318
 
; RG1SAV bit 1 = sprite size (0=8 pixels, 1=16 pixels)
4319
 
;---------------------------------------------------------------------------------------------------------
4320
 
 
4321
 
gfxSetSpriteMode:
4322
 
  and 3                        ; keeps only bits 0 and 1 from A
4323
 
  ld b, a
4324
 
  di
4325
 
    ld a, (BIOS_RG1SAV)         ; get copy from register #1 of VDP
4326
 
    and 0xFC                    ; clear bits 0 and 1 from A
4327
 
    or b                        ; put parameter to A (bits 0 and 1)
4328
 
    ld (BIOS_RG1SAV), a         ; restore to register #1 of VDP
4329
 
    ld b, a                     ; value to write
4330
 
    ld c, 1                     ; register number to write
4331
 
    call gfxWRTVDP     ; write register to VDP
4332
 
    call gfxCLRSPR     ; clear sprites
4333
 
  ei
4334
 
  call gfxGetSpriteSize
4335
 
  jp gfxFillSpriteCollisionTable
4336
 
 
4337
 
endif
4338
 
 
4339
 
if defined SPRITE or defined COLOR_SPRITE or defined PUT_SPRITE_COLOR or defined PUT_SPRITE_STEP_COLOR or defined PUT_SPRITE_COLOR_PATNUM or defined PUT_SPRITE_STEP_COLOR_PATNUM or defined LOAD_SET
4340
 
 
4341
 
;---------------------------------------------------------------------------------------------------------
4342
 
; gfxSetSpriteColorInt
4343
 
; A = sprite number
4344
 
; BC = color number
4345
 
;---------------------------------------------------------------------------------------------------------
4346
 
 
4347
 
gfxSetSpriteColorInt:
4348
 
  ld b, a         ; save sprite number
4349
 
  call gfxCALATR    ; get sprite attribute table address
4350
 
  inc hl
4351
 
  inc hl
4352
 
  inc hl
4353
 
  ld a, c         ; color
4354
 
  ;call gfxSetSpriteColor.Adjust
4355
 
  call gfxWRTVRM
4356
 
 
4357
 
  ld a, (BIOS_SCRMOD)
4358
 
  cp 3
4359
 
  ret c           ; if screen mode < 3, do not adjust sprite multicolor
4360
 
 
4361
 
  ld a, b         ; recover sprite number
4362
 
  call gfxGetSpriteColorTable
4363
 
 
4364
 
  ld a, c         ; color
4365
 
  ;call gfxSetSpriteColor.Adjust
4366
 
  ld b, 16        ; array of 16 bytes
4367
 
 
4368
 
gfxSetSpriteColorInt.1:
4369
 
  push bc
4370
 
    call gfxWRTVRM
4371
 
  pop bc
4372
 
  inc hl
4373
 
  djnz gfxSetSpriteColorInt.1
4374
 
  ret
4375
 
 
4376
 
;gfxSetSpriteColor.Adjust:
4377
 
;  cp 0x0f
4378
 
;  ret z
4379
 
;  ret c
4380
 
;  srl a
4381
 
;  srl a
4382
 
;  srl a
4383
 
;  srl a
4384
 
;  ret
4385
 
 
4386
 
;---------------------------------------------------------------------------------------------------------
4387
 
; gfxSetSpriteColorStr
4388
 
; A = sprite number
4389
 
; DE = address to color byte array
4390
 
; BC = color byte array size
4391
 
;---------------------------------------------------------------------------------------------------------
4392
 
 
4393
 
gfxSetSpriteColorStr:
4394
 
  ld b, a         ; save sprite number
4395
 
  push bc
4396
 
  push de
4397
 
    call gfxCALATR    ; get sprite attribute table
4398
 
  pop de
4399
 
  pop bc
4400
 
 
4401
 
  ld a, c         ; byte array zero length?
4402
 
  or a
4403
 
  ret z
4404
 
 
4405
 
  inc hl
4406
 
  inc hl
4407
 
  inc hl
4408
 
  ld a, (de)      ; color
4409
 
  ;call gfxSetSpriteColor.Adjust
4410
 
  call gfxWRTVRM
4411
 
 
4412
 
  ld a, (BIOS_SCRMOD)
4413
 
  cp 3
4414
 
  ret c           ; if screen mode < 3, do not adjust sprite mode 2
4415
 
 
4416
 
  ld a, b         ; recover sprite number
4417
 
  call gfxGetSpriteColorTable
4418
 
 
4419
 
  ld b, 16        ; array of 16 bytes (color table)
4420
 
  ld a, c         ; size of color array
4421
 
  push de
4422
 
  pop iy          ; save array start
4423
 
 
4424
 
gfxSetSpriteColorStr.1:
4425
 
  push af
4426
 
    ld a, (de)
4427
 
    ;call gfxSetSpriteColor.Adjust
4428
 
    call gfxWRTVRM
4429
 
    inc hl
4430
 
    inc de
4431
 
  pop af
4432
 
  dec a
4433
 
  jr nz, gfxSetSpriteColorStr.2
4434
 
    ld a, c      ; recover array size
4435
 
        push iy
4436
 
        pop de       ; recover array start
4437
 
 
4438
 
gfxSetSpriteColorStr.2:
4439
 
  djnz gfxSetSpriteColorStr.1
4440
 
  ret
4441
 
 
4442
 
 
4443
 
 
4444
 
;---------------------------------------------------------------------------------------------------------
4445
 
; gfxGetSpriteColorTable
4446
 
; A = sprite number
4447
 
; HL = address to color table
4448
 
;---------------------------------------------------------------------------------------------------------
4449
 
 
4450
 
gfxGetSpriteColorTable:
4451
 
  push af
4452
 
  push de
4453
 
    ld h, 0
4454
 
    ld l, a         ; recover sprite number
4455
 
    add hl, hl
4456
 
    add hl, hl
4457
 
    add hl, hl
4458
 
    add hl, hl      ; multiply by 16 (shift left 4)
4459
 
    push hl
4460
 
      xor a
4461
 
      call gfxCALATR    ; get sprite attribute table address
4462
 
    pop de
4463
 
    add hl, de
4464
 
    xor a
4465
 
    ld de, 512
4466
 
    sbc hl, de      ; address of color table from sprite multicolor
4467
 
  pop de
4468
 
  pop af
4469
 
  ret
4470
 
 
4471
 
endif
4472
 
 
4473
 
if defined PUT_SPRITE or defined PUT_SPRITE_STEP or defined PUT_SPRITE_COLOR or defined PUT_SPRITE_STEP_COLOR or defined PUT_SPRITE_COLOR_PATNUM or defined PUT_SPRITE_STEP_COLOR_PATNUM or defined PUT_SPRITE_PATNUM or defined PUT_SPRITE_STEP_PATNUM
4474
 
 
4475
 
;---------------------------------------------------------------------------------------------------------
4476
 
; gfxSetSpriteXY
4477
 
; A = sprite number
4478
 
; BC = XY
4479
 
;---------------------------------------------------------------------------------------------------------
4480
 
 
4481
 
gfxSetSpriteXY:
4482
 
  push bc
4483
 
    call gfxCALATR  ; get sprite attribute table address
4484
 
  pop bc
4485
 
  ld a, c                  ; y
4486
 
  call gfxWRTVRM
4487
 
  inc hl
4488
 
  ld a, b                  ; x
4489
 
  call gfxWRTVRM
4490
 
  ret
4491
 
 
4492
 
;---------------------------------------------------------------------------------------------------------
4493
 
; gfxSpriteStepCheck
4494
 
; BC = XY
4495
 
;---------------------------------------------------------------------------------------------------------
4496
 
 
4497
 
gfxSpriteStepCheck:
4498
 
  push hl
4499
 
  push de
4500
 
  push bc
4501
 
 
4502
 
    ld de, (GFX_SPRITE_SIZE_DAT)
4503
 
    ld a, (GFX_SPRITE_FLAGS)   ; bits 0=chk limits, 1=chk walls, 2=chk hotspots, 3=limit touched, 4=wall touched, 5=hotspot touched, 6=collided
4504
 
    and 7                      ; clear touched and collided flags
4505
 
    ld (GFX_SPRITE_FLAGS), a
4506
 
 
4507
 
    bit 0, a
4508
 
    jr z, gfxSpriteStepCheck.corners
4509
 
 
4510
 
gfxSpriteStepCheck.limits:
4511
 
      ld a, (GFX_MAX_X)
4512
 
      sub e                    ; sprite size
4513
 
      cp b                     ; jump if x > max_x?
4514
 
      jr c, gfxSpriteStepCheck.limits.touched
4515
 
 
4516
 
      ld a, (GFX_MAX_Y)
4517
 
      sub e                    ; sprite size
4518
 
      cp c                     ; jump if y > max_y?
4519
 
      jr c, gfxSpriteStepCheck.limits.touched
4520
 
 
4521
 
      jr gfxSpriteStepCheck.corners
4522
 
 
4523
 
gfxSpriteStepCheck.limits.touched:
4524
 
      ld a, (GFX_SPRITE_FLAGS)   ; bits 0=chk limits, 1=chk walls, 2=chk hotspots, 3=limit touched, 4=wall touched, 5=hotspot touched, 6=collided
4525
 
      or 8                       ; set limit touched flag
4526
 
      ld (GFX_SPRITE_FLAGS), a
4527
 
 
4528
 
gfxSpriteStepCheck.corners:
4529
 
    ld a, (GFX_SPRITE_FLAGS)   ; bits 0=chk limits, 1=chk walls, 2=chk hotspots, 3=limit touched, 4=wall touched, 5=hotspot touched, 6=collided
4530
 
    and 2+4                    ; check walls or hotspots
4531
 
    jr z, gfxSpriteStepCheck.end
4532
 
 
4533
 
      ld (GFX_TEMP10), bc
4534
 
      call gfxSpriteStepCheck.corner
4535
 
 
4536
 
      ld a, (GFX_SPRITE_SIZE_DAT)
4537
 
      add a, b
4538
 
      ld b, a
4539
 
      call gfxSpriteStepCheck.corner
4540
 
 
4541
 
      ld a, (GFX_SPRITE_SIZE_DAT)
4542
 
      add a, c
4543
 
      ld c, a
4544
 
      call gfxSpriteStepCheck.corner
4545
 
 
4546
 
      ld bc, (GFX_TEMP10)
4547
 
      ld a, (GFX_SPRITE_SIZE_DAT)
4548
 
      add a, c
4549
 
      ld c, a
4550
 
      call gfxSpriteStepCheck.corner
4551
 
 
4552
 
gfxSpriteStepCheck.end:
4553
 
  pop bc
4554
 
  pop de
4555
 
  pop hl
4556
 
  ret
4557
 
 
4558
 
gfxSpriteStepCheck.corner:
4559
 
  call gfxGetTileFromXY
4560
 
  ld d, a                ; tile to be searched
4561
 
 
4562
 
  ld a, (GFX_SPRITE_FLAGS)   ; bits 0=chk limits, 1=chk walls, 2=chk hotspots, 3=limit touched, 4=wall touched, 5=hotspot touched, 6=collided
4563
 
  bit 1, a
4564
 
  call nz, gfxSpriteStepCheck.walls
4565
 
 
4566
 
  ld a, (GFX_SPRITE_FLAGS)   ; bits 0=chk limits, 1=chk walls, 2=chk hotspots, 3=limit touched, 4=wall touched, 5=hotspot touched, 6=collided
4567
 
  bit 2, a
4568
 
  call nz, gfxSpriteStepCheck.hotspots
4569
 
  ret
4570
 
 
4571
 
gfxSpriteStepCheck.walls:
4572
 
  ld hl, (GFX_SPRITE_WALLS)
4573
 
  ld e, 16   ; bits 0=chk limits, 1=chk walls, 2=chk hotspots, 3=limit touched, 4=wall touched, 5=hotspot touched, 6=collided
4574
 
  jp gfxSpriteStepCheck.search
4575
 
 
4576
 
gfxSpriteStepCheck.hotspots:
4577
 
  ld hl, (GFX_SPRITE_HOTSPOTS)
4578
 
  ld e, 32   ; bits 0=chk limits, 1=chk walls, 2=chk hotspots, 3=limit touched, 4=wall touched, 5=hotspot touched, 6=collided
4579
 
  call gfxSpriteStepCheck.search
4580
 
 
4581
 
  ld a, (GFX_SPRITE_FLAGS)   ; bits 0=chk limits, 1=chk walls, 2=chk hotspots, 3=limit touched, 4=wall touched, 5=hotspot touched, 6=collided
4582
 
  bit 5, a
4583
 
  ret z
4584
 
 
4585
 
  ld a, (GFX_TEMP1)
4586
 
  ld (GFX_SPRITE_HOTSPOT_TILE), a
4587
 
  ret
4588
 
 
4589
 
; d = tile, hl = search table, e = flag
4590
 
gfxSpriteStepCheck.search:
4591
 
  ld a, h
4592
 
  or l
4593
 
  ret z
4594
 
 
4595
 
  ld a, d   ; search for this tile
4596
 
  push bc
4597
 
     ld c, (hl)
4598
 
     inc hl
4599
 
     ld b, (hl)
4600
 
     inc hl
4601
 
     cpir             ; inc HL searching for A until BC=0 (Z flag settled if found)
4602
 
  pop bc
4603
 
  ret nz
4604
 
 
4605
 
gfxSpriteStepCheck.search.found:
4606
 
  ld a, (GFX_SPRITE_FLAGS)   ; bits 0=chk limits, 1=chk walls, 2=chk hotspots, 3=limit touched, 4=wall touched, 5=hotspot touched, 6=collided
4607
 
  or e                       ; set touched flag
4608
 
  ld (GFX_SPRITE_FLAGS), a
4609
 
  ret
4610
 
 
4611
 
; b = x, c = y
4612
 
gfxGetTileFromXY:
4613
 
  push bc
4614
 
    ld a, c   ; y
4615
 
    srl b     ; divide by 2
4616
 
    srl b     ; divide by 4
4617
 
    srl b     ; divide by 8
4618
 
    ld c, b
4619
 
    srl a
4620
 
    srl a
4621
 
    srl a
4622
 
    ld b, a
4623
 
    call gfxGetScreenTile   ; b = y, c = x, a = tile
4624
 
  pop bc
4625
 
  ret
4626
 
 
4627
 
endif
4628
 
 
4629
 
if defined SPRITE or defined PUT_SPRITE or defined PUT_SPRITE_PATNUM or defined PUT_SPRITE_STEP_PATNUM or defined PUT_SPRITE_COLOR_PATNUM or defined PUT_SPRITE_STEP_COLOR_PATNUM
4630
 
 
4631
 
;---------------------------------------------------------------------------------------------------------
4632
 
; gfxSetSpritePattern
4633
 
; A = sprite number
4634
 
; BC = pattern number
4635
 
;---------------------------------------------------------------------------------------------------------
4636
 
 
4637
 
gfxSetSpritePattern:
4638
 
  push bc
4639
 
    call gfxCALATR   ; get sprite attribute table address
4640
 
  pop bc
4641
 
  inc hl
4642
 
  inc hl
4643
 
  ld a, (BIOS_RG1SAV)           ; bit 0 = double size, bit 1 = sprite size (0=8 pixels, 1=16 pixels)
4644
 
  bit 1, a
4645
 
  jr z, gfxSetSpritePattern.1
4646
 
    sll c
4647
 
    sll c
4648
 
gfxSetSpritePattern.1:
4649
 
  ld a, c                   ; pattern number
4650
 
  call gfxWRTVRM
4651
 
  ret
4652
 
 
4653
 
endif
4654
 
 
4655
 
if defined SPRITE
4656
 
 
4657
 
;---------------------------------------------------------------------------------------------------------
4658
 
; gfxSetSpriteData
4659
 
; HL = point to sprite data as a string of 8 or 32 characters according the sprites size (8x8 or 16x16)
4660
 
; A = sprite number
4661
 
;---------------------------------------------------------------------------------------------------------
4662
 
 
4663
 
gfxSetSpriteData:
4664
 
  push AF
4665
 
    push HL
4666
 
      call gfxCALPAT    ; get sprite pattern data address
4667
 
      ex DE, HL
4668
 
      call gfxGSPSIZ    ; return in 'a' sprite default size
4669
 
    pop HL
4670
 
    ld b, 0
4671
 
        cp c
4672
 
        jr z,  gfxSetSpriteData.1
4673
 
        jr nc, gfxSetSpriteData.1
4674
 
      ld c, a
4675
 
gfxSetSpriteData.1:
4676
 
        push bc
4677
 
          ld c, a
4678
 
      xor a
4679
 
          call gfxFILVRM
4680
 
        pop bc
4681
 
  pop AF
4682
 
  call gfxLDIRVM
4683
 
  ret
4684
 
 
4685
 
endif
4686
 
 
4687
 
if defined GFX_SPRITES
4688
 
 
4689
 
;---------------------------------------------------------------------------------------------------------
4690
 
; gfxInitSprites
4691
 
; initialises all sprites
4692
 
;---------------------------------------------------------------------------------------------------------
4693
 
 
4694
 
gfxInitSprites:
4695
 
  call gfxCLRSPR
4696
 
  ret
4697
 
 
4698
 
;---------------------------------------------------------------------------------------------------------
4699
 
; gfxSetSpriteAttrs
4700
 
; set sprite default x, y, pattern and color
4701
 
; A = sprite number
4702
 
;---------------------------------------------------------------------------------------------------------
4703
 
 
4704
 
gfxSetSpriteAttrs:
4705
 
  push af
4706
 
    call gfxCALATR
4707
 
    ld a, (BIOS_GRPACY)   ; y
4708
 
        call gfxWRTVRM
4709
 
        inc hl
4710
 
    ld a, (BIOS_GRPACX)   ; x
4711
 
        call gfxWRTVRM
4712
 
        inc hl
4713
 
  pop af                  ; pattern
4714
 
  call gfxWRTVRM
4715
 
  inc hl
4716
 
  ld a, (BIOS_FORCLR)     ; color
4717
 
  call gfxWRTVRM
4718
 
  ret
4719
 
 
4720
 
endif
4721
 
 
4722
 
if defined EXIST_DATA_SET
4723
 
 
4724
 
;---------------------------------------------------------------------------------------------------------
4725
 
; gfxIsTileMode
4726
 
;---------------------------------------------------------------------------------------------------------
4727
 
 
4728
 
gfxIsTileMode:
4729
 
    ld a, (BIOS_SCRMOD)
4730
 
    cp 2
4731
 
    ret z
4732
 
    cp 4
4733
 
    ret
4734
 
 
4735
 
;---------------------------------------------------------------------------------------------------------
4736
 
; gfxClearTileScreen
4737
 
;---------------------------------------------------------------------------------------------------------
4738
 
 
4739
 
gfxClearTileScreen:
4740
 
    ld a, 0x20           ; space
4741
 
    ld bc, 768
4742
 
    ld hl, (BIOS_GRPNAM)
4743
 
    call gfxFILVRM
4744
 
 
4745
 
    ld de, 0x0020
4746
 
    call gfxSetTileDefaultColor
4747
 
    ld de, 0x0120
4748
 
    call gfxSetTileDefaultColor
4749
 
    ld de, 0x0220
4750
 
    jp gfxSetTileDefaultColor
4751
 
 
4752
 
gfxSetTileDefaultColor
4753
 
    call gfxGetTileColorAddr
4754
 
    ex de, hl
4755
 
    call gfxGetTileDefaultColor
4756
 
    ld bc, 8
4757
 
    jp gfxFILVRM
4758
 
 
4759
 
gfxGetTileDefaultColor:
4760
 
    ld a, (BIOS_FORCLR)
4761
 
    sla a
4762
 
    sla a
4763
 
    sla a
4764
 
    sla a
4765
 
    push hl
4766
 
      ld hl, BIOS_BAKCLR
4767
 
      or (hl)
4768
 
    pop hl
4769
 
    ret
4770
 
 
4771
 
; set tile color
4772
 
; HL = tile color pointer
4773
 
; BC = tile color size
4774
 
; DE = tile number
4775
 
 
4776
 
;---------------------------------------------------------------------------------------------------------
4777
 
; gfxSetTileData
4778
 
; set tile data
4779
 
; HL = tile data pointer
4780
 
; BC = tile data size
4781
 
; DE = tile number
4782
 
; A = flip (0=no, 1=yes)
4783
 
;---------------------------------------------------------------------------------------------------------
4784
 
 
4785
 
gfxSetTileData:
4786
 
  or a
4787
 
  jr nz, gfxSetTileDataFlip
4788
 
 
4789
 
gfxSetTileDataNoFlip:
4790
 
  call gfxGetTileDataAddr
4791
 
  jp gfxLDIRVM
4792
 
 
4793
 
gfxSetTileDataFlip:
4794
 
  call gfxGetTileDataAddr
4795
 
  ex de, hl
4796
 
gfxSetTileDataFlip.Loop:
4797
 
  ld a, (de)
4798
 
  call gfxReverseA
4799
 
  call gfxWRTVRM
4800
 
  inc de
4801
 
  inc hl
4802
 
  dec bc
4803
 
  ld a, b
4804
 
  cp c
4805
 
  jr nz, gfxSetTileDataFlip.Loop
4806
 
  ret
4807
 
 
4808
 
; in de = tile number
4809
 
; out de = tile number address
4810
 
gfxGetTileDataAddr:
4811
 
  push hl
4812
 
    ex de, hl
4813
 
    add hl, hl
4814
 
    add hl, hl
4815
 
    add hl, hl   ; tile number * 8
4816
 
    ld de, (BIOS_GRPCGP)
4817
 
    add hl, de
4818
 
    ex de, hl
4819
 
  pop hl
4820
 
  ret
4821
 
 
4822
 
;---------------------------------------------------------------------------------------------------------
4823
 
; gfxSetTileColor
4824
 
; set tile color
4825
 
; HL = tile color pointer
4826
 
; BC = tile color size
4827
 
; DE = tile number
4828
 
;---------------------------------------------------------------------------------------------------------
4829
 
 
4830
 
gfxSetTileColor:
4831
 
  call gfxGetTileColorAddr
4832
 
  jp gfxLDIRVM
4833
 
 
4834
 
; in de = tile number
4835
 
; out de = tile number address
4836
 
gfxGetTileColorAddr:
4837
 
  push hl
4838
 
    ex de, hl
4839
 
    add hl, hl
4840
 
    add hl, hl
4841
 
    add hl, hl   ; tile number * 8
4842
 
    ld de, (BIOS_GRPCOL)
4843
 
    add hl, de
4844
 
    ex de, hl
4845
 
  pop hl
4846
 
  ret
4847
 
 
4848
 
;---------------------------------------------------------------------------------------------------------
4849
 
; gfxSetScreenTile
4850
 
; set screen tile at x,y
4851
 
; C = x
4852
 
; B = y
4853
 
; a = tile number
4854
 
;---------------------------------------------------------------------------------------------------------
4855
 
 
4856
 
gfxSetScreenTile:
4857
 
  ex af, af'
4858
 
  ld a, 23
4859
 
  cp b
4860
 
  ret c
4861
 
  ld a, 31
4862
 
  cp c
4863
 
  ret c
4864
 
  ;push bc
4865
 
  ;  ld h, 0
4866
 
  ;  ld l, b      ; slow y * 32
4867
 
  ;  ld bc, 32
4868
 
  ;  call MATH.MULT.16
4869
 
  ;pop bc
4870
 
  ld h, b
4871
 
  sra h
4872
 
  sra h
4873
 
  sra h
4874
 
  ld l, b
4875
 
  sla l
4876
 
  sla l
4877
 
  sla l
4878
 
  sla l
4879
 
  sla l            ; fast y * 32
4880
 
  ld d, 0
4881
 
  ld e, c        ; x
4882
 
  add hl, de
4883
 
  ld de, (BIOS_GRPNAM)
4884
 
  add hl, de
4885
 
  ex af, af'
4886
 
  jp gfxWRTVRM
4887
 
 
4888
 
endif
4889
 
 
4890
 
if defined gfxGetTileFromXY or defined EXIST_DATA_SET
4891
 
 
4892
 
;---------------------------------------------------------------------------------------------------------
4893
 
; gfxGetScreenTile
4894
 
; get screen tile at x,y
4895
 
; C = x
4896
 
; B = y
4897
 
; a = tile number
4898
 
;---------------------------------------------------------------------------------------------------------
4899
 
 
4900
 
gfxGetScreenTile:
4901
 
  ld a, 23
4902
 
  cp b
4903
 
  ret c
4904
 
  ld a, 31
4905
 
  cp c
4906
 
  ret c
4907
 
  ld h, b
4908
 
  sra h
4909
 
  sra h
4910
 
  sra h
4911
 
  ld l, b
4912
 
  sla l
4913
 
  sla l
4914
 
  sla l
4915
 
  sla l
4916
 
  sla l            ; fast y * 32
4917
 
  ld d, 0
4918
 
  ld e, c        ; x
4919
 
  add hl, de
4920
 
  ld de, (BIOS_GRPNAM)
4921
 
  add hl, de
4922
 
  jp gfxRDVRM
4923
 
 
4924
 
endif
4925
 
 
4926
 
;---------------------------------------------------------------------------------------------------------
4927
 
; Sprite collision table routines
4928
 
;---------------------------------------------------------------------------------------------------------
4929
 
 
4930
 
gfxInitSpriteCollisionTable:
4931
 
  ld bc, 128
4932
 
  call memory.alloc
4933
 
  ld (GFX_SPRITE_COLLISION), ix
4934
 
  ret
4935
 
 
4936
 
; copy sprite attribute table to ram
4937
 
gfxFillSpriteCollisionTable:
4938
 
  ld hl, (BIOS_ATRBAS)          ; source: attribute table
4939
 
  ld de, (GFX_SPRITE_COLLISION) ; dest: ram
4940
 
  ld bc, 128                    ; 32*4 = size of attribute table
4941
 
  call gfxLDIRMV
4942
 
 
4943
 
; pre-calculate each sprite width
4944
 
gfxCalculateSpriteCollisionTable:
4945
 
  ld ix, (GFX_SPRITE_COLLISION)   ; start of sprites attributes
4946
 
  ld b, 32                        ; sprite count
4947
 
 
4948
 
gfxCalculateSpriteCollisionTable.start:
4949
 
  ld a, (GFX_SPRITE_SIZE_DAT)     ; sprite size
4950
 
  ld c, a
4951
 
  ld d, 208                       ; Y no-display flag
4952
 
 
4953
 
  ; test screen mode
4954
 
  ld a, (BIOS_SCRMOD)
4955
 
  cp 3           ; above screen 3?
4956
 
  jr c, gfxCalculateSpriteCollisionTable.next
4957
 
        ld d, 216    ; Y no-display flag
4958
 
 
4959
 
gfxCalculateSpriteCollisionTable.next:
4960
 
  ; test IC flag (no collision) in color table
4961
 
  ; test EC flag (early clock, shift 32 dots to the left) in color table
4962
 
  ; set x1 = x + size, y1 = y + size
4963
 
  ld a, (ix)   ; y
4964
 
  cp d         ; test if sprite will not be displayed
4965
 
  ret z
4966
 
 
4967
 
  add a, c
4968
 
  ld (ix+2), a ; y1
4969
 
  ld a, (ix+1) ; x
4970
 
  add a, c
4971
 
  ld (ix+3), a ; x1
4972
 
 
4973
 
  inc ix
4974
 
  inc ix
4975
 
  inc ix
4976
 
  inc ix
4977
 
  djnz gfxCalculateSpriteCollisionTable.next
4978
 
  ret
4979
 
 
4980
 
; BC = sprite number to check
4981
 
gfxUpdateSpriteCollisionTable:
4982
 
  ld (BIOS_TEMP), bc
4983
 
  ld h, b
4984
 
  ld l, c
4985
 
  add hl, hl
4986
 
  add hl, hl
4987
 
  ld b, h
4988
 
  ld c, l
4989
 
  ld hl, (GFX_SPRITE_COLLISION) ; dest: ram
4990
 
  add hl, bc
4991
 
  ex de, hl
4992
 
  ld hl, (BIOS_ATRBAS)          ; source: attribute table
4993
 
  add hl, bc
4994
 
  ld bc, 4                      ; 4 = size of attribute table to 1 sprite]
4995
 
  push de
4996
 
    call gfxLDIRMV
4997
 
  pop ix
4998
 
  ld b, 1                       ; sprite count
4999
 
  push ix
5000
 
    call gfxCalculateSpriteCollisionTable.start
5001
 
  pop iy
5002
 
 
5003
 
  ld a, (GFX_SPRITE_FLAGS)
5004
 
  and 0xBF                      ; clear collision flag
5005
 
  ld (GFX_SPRITE_FLAGS), a
5006
 
 
5007
 
  ld a, (BIOS_STATFL)           ; verify if collision occurred
5008
 
  bit 5, a
5009
 
  ret z
5010
 
  jr gfxCheckSpriteCollisionTable.start
5011
 
 
5012
 
; BC = sprite number to check
5013
 
gfxCheckSpriteCollisionTable:
5014
 
  ; get target sprite address (iy)
5015
 
  ld (BIOS_TEMP), bc
5016
 
  ld h, b
5017
 
  ld l, c
5018
 
  ld de, (GFX_SPRITE_COLLISION)
5019
 
  add hl, hl            ; x4
5020
 
  add hl, hl
5021
 
  add hl, de
5022
 
  push hl
5023
 
  pop iy
5024
 
 
5025
 
gfxCheckSpriteCollisionTable.start:
5026
 
  ; start test against others sprites
5027
 
  ld ix, (GFX_SPRITE_COLLISION)
5028
 
  ld bc, 0
5029
 
  ld d, 208      ; Y no-display flag
5030
 
 
5031
 
  ; test screen mode
5032
 
  ld a, (BIOS_SCRMOD)
5033
 
  cp 3           ; above screen 3?
5034
 
  jr c, gfxCheckSpriteCollisionTable.test
5035
 
    ld d, 216    ; Y no-display flag
5036
 
 
5037
 
gfxCheckSpriteCollisionTable.test:
5038
 
  ; skip target sprite
5039
 
  ld a, (BIOS_TEMP)
5040
 
  cp c
5041
 
  jr z, gfxCheckSpriteCollisionTable.next
5042
 
 
5043
 
  ; test if x1 > nx and x < nx1 and y1 > ny and y < ny1
5044
 
  ld a, (ix)   ; ny
5045
 
  cp d         ; test if sprite will not be displayed
5046
 
  ret z        ; return false
5047
 
 
5048
 
  cp (iy+2)    ; y1
5049
 
  jr nc, gfxCheckSpriteCollisionTable.next
5050
 
 
5051
 
  ld a, (ix+1) ; nx
5052
 
  cp (iy+3)    ; x1
5053
 
  jr nc, gfxCheckSpriteCollisionTable.next
5054
 
 
5055
 
  ld a, (iy+1) ; x
5056
 
  cp (ix+3)    ; nx1
5057
 
  jr nc, gfxCheckSpriteCollisionTable.next
5058
 
 
5059
 
  ld a, (iy)   ; y
5060
 
  cp (ix+2)    ; ny1
5061
 
  jr nc, gfxCheckSpriteCollisionTable.next
5062
 
 
5063
 
  ; if so, save collider sprite
5064
 
  ld a, c
5065
 
  ld (GFX_SPRITE_COLLIDER), a
5066
 
 
5067
 
  ld a, (GFX_SPRITE_FLAGS)
5068
 
  or 0x40                      ; set collision flag
5069
 
  ld (GFX_SPRITE_FLAGS), a
5070
 
  ret                          ; return true
5071
 
 
5072
 
  ; else, next
5073
 
gfxCheckSpriteCollisionTable.next:
5074
 
  inc c
5075
 
  inc ix
5076
 
  inc ix
5077
 
  inc ix
5078
 
  inc ix
5079
 
  ld a, 32
5080
 
  cp c
5081
 
  ret z                           ; return false
5082
 
  jr gfxCheckSpriteCollisionTable.test
5083
 
 
5084
 
 
5085
 
 
5086
 
;---------------------------------------------------------------------------------------------------------
5087
 
; VDP / VRAM support routines
5088
 
;---------------------------------------------------------------------------------------------------------
5089
 
 
5090
 
; WRITE TO VDP
5091
 
; in b = data
5092
 
;    c = register number
5093
 
;    a = register number
5094
 
gfxWRTVDP:
5095
 
  bit 7, a
5096
 
  ret nz                ; is negative? read only
5097
 
  cp 8
5098
 
  ret z                 ; is register 8? then status register 0 (read only)
5099
 
  jr nc, gfxWRTVDP.1    ; is > 8? then control registers numbers added 1
5100
 
  jr gfxWRTVDP.3
5101
 
gfxWRTVDP.1:
5102
 
  ld ix, BIOS_SCRMOD
5103
 
  bit 3, (ix)
5104
 
  jr nz, gfxWRTVDP.2
5105
 
  bit 2, (ix)
5106
 
  jr nz, gfxWRTVDP.2
5107
 
  ret
5108
 
gfxWRTVDP.2:
5109
 
  dec a
5110
 
  ld c, a
5111
 
gfxWRTVDP.3:
5112
 
  ;ld ix, BIOS_SCRMOD
5113
 
  ;bit 3, (ix)
5114
 
  ;jp nz, BIOS_NWRVDP    ; msx 2
5115
 
  ;bit 2, (ix)
5116
 
  ;jp nz, BIOS_NWRVDP    ; msx 2
5117
 
  jp BIOS_WRTVDP        ; msx 1
5118
 
 
5119
 
; READ FROM VDP
5120
 
; in  a = register number
5121
 
; out a = data
5122
 
gfxRDVDP:
5123
 
  bit 7, a
5124
 
  jr nz, gfxRDVDP.1     ; is negative? then status register 1 to 9
5125
 
  cp 8
5126
 
  jr z,  gfxRDVDP.2     ; is register 8? then status register 0
5127
 
  cp 9
5128
 
  jr nc, gfxRDVDP.3     ; is >= 9? then control registers numbers added 1
5129
 
    ld hl, BIOS_RG0SAV  ; else is correct control registers numbers
5130
 
    jr gfxRDVDP.4
5131
 
gfxRDVDP.1:
5132
 
  ld ix, BIOS_SCRMOD
5133
 
  bit 3, (ix)
5134
 
  jr nz, gfxRDVDP.1.a
5135
 
  bit 2, (ix)
5136
 
  jr nz, gfxRDVDP.1.a
5137
 
  xor a
5138
 
  ret
5139
 
gfxRDVDP.1.a:
5140
 
  neg
5141
 
  jp BIOS_NRDVDP   ;BIOS_VDPSTA
5142
 
gfxRDVDP.2:
5143
 
  ld a, (BIOS_STATFL)
5144
 
  ret
5145
 
  ;xor a
5146
 
  ;jp BIOS_VDPSTA
5147
 
gfxRDVDP.3:
5148
 
  ld hl, BIOS_RG8SAV-9
5149
 
gfxRDVDP.4:
5150
 
  ld d, 0
5151
 
  ld e, a
5152
 
  add hl,de
5153
 
  ld a, (hl)
5154
 
  ret
5155
 
 
5156
 
; in: A=Data byte, BC=Length, HL=VRAM address
5157
 
gfxFILVRM:
5158
 
  ld ix, BIOS_SCRMOD
5159
 
  bit 3, (ix)
5160
 
  jp nz, BIOS_BIGFIL
5161
 
  bit 2, (ix)
5162
 
  jp nz, BIOS_BIGFIL
5163
 
  jp BIOS_FILVRM
5164
 
 
5165
 
; in: A=Sprite pattern number
5166
 
; out: HL=Sprite pattern address
5167
 
gfxCALPAT:
5168
 
  ld iy, BIOS_SCRMOD
5169
 
  ld ix, BIOS_CALPAT2
5170
 
  bit 3, (iy)
5171
 
  jp nz, BIOS_EXTROM
5172
 
  bit 2, (iy)
5173
 
  jp nz, BIOS_EXTROM
5174
 
  jp BIOS_CALPAT
5175
 
 
5176
 
; in: A=Sprite number
5177
 
; out: HL=Sprite attribute address
5178
 
gfxCALATR:
5179
 
  ld iy, BIOS_SCRMOD
5180
 
  ld ix, BIOS_CALATR2
5181
 
  bit 3, (iy)
5182
 
  jp nz, BIOS_EXTROM
5183
 
  bit 2, (iy)
5184
 
  jp nz, BIOS_EXTROM
5185
 
  jp BIOS_CALATR
5186
 
 
5187
 
; out: A=Bytes in sprite pattern (8 or 32)
5188
 
gfxGSPSIZ:
5189
 
  ld iy, BIOS_SCRMOD
5190
 
  ld ix, BIOS_GSPSIZ2
5191
 
  bit 3, (iy)
5192
 
  jp nz, BIOS_EXTROM
5193
 
  bit 2, (iy)
5194
 
  jp nz, BIOS_EXTROM
5195
 
  jp BIOS_GSPSIZ
5196
 
 
5197
 
gfxCLRSPR:
5198
 
  ld iy, BIOS_SCRMOD
5199
 
  ld ix, BIOS_CLRSPR2
5200
 
  bit 3, (iy)
5201
 
  jp nz, BIOS_EXTROM
5202
 
  bit 2, (iy)
5203
 
  jp nz, BIOS_EXTROM
5204
 
  jp BIOS_CLRSPR
5205
 
 
5206
 
; RAM to VRAM
5207
 
; in: BC=Length, dest DE=VRAM address, source HL=RAM address
5208
 
gfxLDIRVM:
5209
 
  jp BIOS_LDIRVM
5210
 
 
5211
 
; VRAM to RAM
5212
 
; in: BC=Length, dest DE=RAM address, source HL=VRAM address
5213
 
gfxLDIRMV:
5214
 
  jp BIOS_LDIRMV
5215
 
 
5216
 
; WRITE TO VRAM
5217
 
; in hl = address
5218
 
;     a = data
5219
 
gfxWRTVRM:
5220
 
  ld ix, BIOS_SCRMOD
5221
 
  bit 3, (ix)
5222
 
  jp nz, BIOS_NWRVRM
5223
 
  bit 2, (ix)
5224
 
  jp nz, BIOS_NWRVRM
5225
 
  jp BIOS_WRTVRM
5226
 
 
5227
 
; READ FROM VRAM
5228
 
; in hl = address
5229
 
; out a = data
5230
 
gfxRDVRM:
5231
 
  ld ix, BIOS_SCRMOD
5232
 
  bit 3, (ix)
5233
 
  jp nz, BIOS_NRDVRM
5234
 
  bit 2, (ix)
5235
 
  jp nz, BIOS_NRDVRM
5236
 
  jp BIOS_RDVRM
5237
 
 
5238
 
; reverse bits in A
5239
 
; 8 bytes / 206 cycles
5240
 
; http://www.retroprogramming.com/2014/01/fast-z80-bit-reversal.html
5241
 
gfxReverseA:
5242
 
  ld b,8
5243
 
  ld l,a
5244
 
gfxReverseA.loop:
5245
 
  rl l
5246
 
  rra
5247
 
  djnz gfxReverseA.loop
5248
 
  ret
5249
 
 
5250
 
 
5251
 
 
5252
 
;---------------------------------------------------------------------------------------------------------
5253
 
; MATH PACK WRAPPER
5254
 
;---------------------------------------------------------------------------------------------------------
5255
 
 
5256
 
CALL_MATH_LIB: exx
5257
 
                             ld hl, RET_MATH_LIB
5258
 
                             push hl
5259
 
                   ld hl, BASIC_DAC
5260
 
                   ld de, BASIC_ARG
5261
 
                               ld bc, BASIC_SWPTMP
5262
 
                   jp (ix)
5263
 
RET_MATH_LIB:    call COPY_TO.TMP_DAC
5264
 
               exx
5265
 
               ret
5266
 
 
5267
 
if defined MATH.ADD
5268
 
 
5269
 
MATH_DECADD:   ld ix, addSingle
5270
 
               jp CALL_MATH_LIB
5271
 
 
5272
 
endif
5273
 
 
5274
 
if defined MATH.SUB or defined MATH.NEG
5275
 
 
5276
 
MATH_DECSUB:   ld ix, subSingle
5277
 
                           jp CALL_MATH_LIB
5278
 
 
5279
 
endif
5280
 
 
5281
 
if defined MATH.MULT
5282
 
 
5283
 
MATH_DECMUL:   ld ix, mulSingle
5284
 
                           jp CALL_MATH_LIB
5285
 
 
5286
 
endif
5287
 
 
5288
 
if defined MATH.DIV
5289
 
 
5290
 
MATH_DECDIV:   ld ix, divSingle
5291
 
                           jp CALL_MATH_LIB
5292
 
 
5293
 
endif
5294
 
 
5295
 
if defined MATH.POW
5296
 
 
5297
 
MATH_DBLEXP:
5298
 
MATH_SNGEXP:   ld ix, powSingle
5299
 
                           jp CALL_MATH_LIB
5300
 
 
5301
 
endif
5302
 
 
5303
 
if defined COS
5304
 
 
5305
 
MATH_COS:      ld ix, cosSingle
5306
 
                           jp CALL_MATH_LIB
5307
 
 
5308
 
endif
5309
 
 
5310
 
if defined SIN
5311
 
 
5312
 
MATH_SIN:      ld ix, sinSingle
5313
 
                           jp CALL_MATH_LIB
5314
 
 
5315
 
endif
5316
 
 
5317
 
if defined TAN
5318
 
 
5319
 
MATH_TAN:      ld ix, tanSingle
5320
 
                           jp CALL_MATH_LIB
5321
 
 
5322
 
endif
5323
 
 
5324
 
if defined ATN
5325
 
 
5326
 
MATH_ATN:      ld ix, atanSingle
5327
 
                           jp CALL_MATH_LIB
5328
 
 
5329
 
endif
5330
 
 
5331
 
if defined SQR
5332
 
 
5333
 
MATH_SQR:      ld ix, sqrtSingle
5334
 
                           jp CALL_MATH_LIB
5335
 
 
5336
 
endif
5337
 
 
5338
 
if defined LOG
5339
 
 
5340
 
MATH_LOG:      ld ix, lnSingle
5341
 
                           jp CALL_MATH_LIB
5342
 
 
5343
 
endif
5344
 
 
5345
 
if defined EXP
5346
 
 
5347
 
MATH_EXP:      ld ix, expSingle
5348
 
                           jp CALL_MATH_LIB
5349
 
 
5350
 
endif
5351
 
 
5352
 
if defined ABS
5353
 
 
5354
 
MATH_ABSFN:    ld ix, absSingle
5355
 
                           jp CALL_MATH_LIB
5356
 
 
5357
 
endif
5358
 
 
5359
 
if defined MATH.SEED or defined MATH.NEG
5360
 
 
5361
 
MATH_NEG:      ld ix, negSingle
5362
 
                           jp CALL_MATH_LIB
5363
 
 
5364
 
endif
5365
 
 
5366
 
if defined SGN
5367
 
 
5368
 
MATH_SGN:      ld ix, sgnSingle
5369
 
                           jp CALL_MATH_LIB
5370
 
 
5371
 
endif
5372
 
 
5373
 
if defined RND or defined MATH.SEED
5374
 
 
5375
 
MATH_RND:      ld ix, randSingle
5376
 
               jp CALL_MATH_LIB
5377
 
 
5378
 
endif
5379
 
 
5380
 
MATH_FRCINT:   ld hl, BASIC_DAC
5381
 
               ld bc, BASIC_DAC+2
5382
 
                           call single2Int
5383
 
                           ld ix, BASIC_DAC
5384
 
                           ld (ix), 0
5385
 
                           ld (ix+1), 0
5386
 
                           ;ld (ix+2), l
5387
 
                           ;ld (ix+3), h
5388
 
                           ld (ix+4), 0
5389
 
                           ld (ix+5), 0
5390
 
                           ld (ix+6), 0
5391
 
                           ld (ix+7), 0
5392
 
               ld a, 2
5393
 
               ld (BASIC_VALTYP), a
5394
 
               ret
5395
 
 
5396
 
MATH_FRCDBL:                         ; same as MATH_FRCSGL
5397
 
MATH_FRCSGL:   ld hl, BASIC_DAC+2    ; input address
5398
 
               ld bc, BASIC_DAC      ; output address
5399
 
               call int2Single
5400
 
               ld a, 8
5401
 
               ld (BASIC_VALTYP), a
5402
 
               ret
5403
 
 
5404
 
MATH_ICOMP:         ld a, h   ; cp hl, de (alternative to bios DCOMPR)
5405
 
                    cp d
5406
 
                                jr nz, MATH_ICOMP.NE.HIGH
5407
 
                                  ld a, l
5408
 
                                  cp e
5409
 
                                  jr nz, MATH_ICOMP.NE.LOW
5410
 
                        jr MATH_DCOMP.EQ
5411
 
MATH_ICOMP.NE.HIGH: jr c, MATH_ICOMP.GT.HIGH
5412
 
                    bit 7, a
5413
 
                    jr nz, MATH_DCOMP.GT
5414
 
                                  jr MATH_DCOMP.LT
5415
 
MATH_ICOMP.GT.HIGH: bit 7, d
5416
 
                    jr z, MATH_DCOMP.GT
5417
 
                                  jr MATH_DCOMP.LT
5418
 
MATH_ICOMP.NE.LOW:  jr c, MATH_DCOMP.GT
5419
 
                                  jr MATH_DCOMP.LT
5420
 
 
5421
 
MATH_XDCOMP:                          ; same as MATH_DCOMP
5422
 
MATH_DCOMP:    ld ix, cmpSingle
5423
 
                           call CALL_MATH_LIB
5424
 
                           jr z, MATH_DCOMP.EQ
5425
 
                           jr c, MATH_DCOMP.LT
5426
 
MATH_DCOMP.GT: ld a, 0xFF             ; DAC > ARG
5427
 
               ret
5428
 
MATH_DCOMP.EQ: ld a, 0                ; DAC = ARG
5429
 
               ret
5430
 
MATH_DCOMP.LT: ld a, 1                ; DAC < ARG
5431
 
               ret
5432
 
 
5433
 
if defined CAST_STR_TO.VAL
5434
 
 
5435
 
MATH_FIN:      ; HL has the source string
5436
 
               ld a, (BASIC_VALTYP)
5437
 
               cp 2                   ; test if integer
5438
 
                           jr nz, MATH_FIN.1
5439
 
                           ld hl, (BASIC_DAC+2)
5440
 
                           ld de, BASIC_STRBUF
5441
 
                           call StrToInt
5442
 
                           ld hl, BASIC_STRBUF
5443
 
                           ret
5444
 
MATH_FIN.1:        ld BC, BASIC_DAC
5445
 
                           call str2single
5446
 
               ret
5447
 
 
5448
 
endif
5449
 
 
5450
 
if defined CAST_INT_TO.STR
5451
 
 
5452
 
MATH_FOUT:     ld a, (BASIC_VALTYP)
5453
 
               cp 2                   ; test if integer
5454
 
                           jr nz, MATH_FOUT.1
5455
 
                           ld hl, (BASIC_DAC+2)
5456
 
                           ld de, BASIC_STRBUF
5457
 
                           call IntToStr
5458
 
                           ld hl, BASIC_STRBUF
5459
 
                           ret
5460
 
MATH_FOUT.1:   ld hl, BASIC_DAC
5461
 
               ld bc, BASIC_STRBUF
5462
 
               call single2str
5463
 
                           ld hl, BASIC_STRBUF
5464
 
               ret
5465
 
 
5466
 
endif
5467
 
 
5468
 
 
5469
 
 
5470
 
 
5471
 
;---------------------------------------------------------------------------------------------------------
5472
 
; Z80FLOAT LIBRARY
5473
 
; Copyright 2018 Zeda A.K. Thomas
5474
 
;---------------------------------------------------------------------------------------------------------
5475
 
; References:
5476
 
; https://github.com/Zeda/z80float
5477
 
; https://www.omnimaga.org/asm-language/(z80)-floating-point-routines/
5478
 
; https://en.wikipedia.org/wiki/Single-precision_floating-point_format
5479
 
;---------------------------------------------------------------------------------------------------------
5480
 
; Parameters:
5481
 
; HL points to the first operand
5482
 
; DE points to the second operand (if needed)
5483
 
; IX points to the third operand (if needed, rare)
5484
 
; BC points to where the result should be output
5485
 
; Floats are stored by a little-endian 24-bit mantissa. However, the highest bit
5486
 
; is taken as implicitly 1, so we replace it as a sign bit. Next comes an 8-bit
5487
 
; exponent biased by +128.
5488
 
;---------------------------------------------------------------------------------------------------------
5489
 
; Adapted to MSXBas2Asm by Amaury Carvalho, 2019
5490
 
;---------------------------------------------------------------------------------------------------------
5491
 
 
5492
 
;---------------------------------------------------------------------------------------------------------
5493
 
; Work area
5494
 
;---------------------------------------------------------------------------------------------------------
5495
 
 
5496
 
BASIC_HOLD8: equ 0xF806  ;      48      Work area for decimal multiplications.
5497
 
BASIC_HOLD2: equ 0xF836  ;      8       Work area in the execution of numerical operators.
5498
 
BASIC_HOLD:  equ 0xF83E  ;  8   Work area in the execution of numerical operators.
5499
 
scrap:   equ BASIC_HOLD8
5500
 
seed0:   equ BASIC_RNDX
5501
 
seed1:   equ seed0 + 4
5502
 
var48:   equ scrap + 4
5503
 
quot:    equ scrap + 1
5504
 
addend:  equ scrap
5505
 
addend2: equ scrap+7           ;4 bytes
5506
 
var_x:   equ BASIC_HOLD8 + 4   ;4 bytes
5507
 
var_y:   equ var_x + 4         ;4 bytes
5508
 
var_z:   equ var_y + 4         ;4 bytes
5509
 
var_a:   equ var_z + 4         ;4 bytes
5510
 
var_b:   equ var_a + 4         ;4 bytes
5511
 
var_c:   equ var_b + 4         ;4 bytes
5512
 
temp:    equ var_c + 4         ;4 bytes
5513
 
temp1:   equ temp  + 4         ;4 bytes
5514
 
temp2:   equ temp1 + 4         ;4 bytes
5515
 
temp3:   equ temp2 + 4         ;4 bytes
5516
 
 
5517
 
pow10exp_single: equ scrap+9
5518
 
strout_single:   equ 0xF750    ;  PARM2 - BASIC_BUF   ;pow10exp_single+2
5519
 
 
5520
 
;---------------------------------------------------------------------------------------------------------
5521
 
; addSingle
5522
 
;---------------------------------------------------------------------------------------------------------
5523
 
 
5524
 
;;Still need to tend to special cases
5525
 
addSingle:
5526
 
;;x+y
5527
 
    push af
5528
 
    push hl
5529
 
    push de
5530
 
    push bc
5531
 
addInject:
5532
 
    inc de
5533
 
    inc de
5534
 
    inc hl
5535
 
    inc hl
5536
 
    ld a,(de)
5537
 
    xor (hl)
5538
 
    push af
5539
 
    inc de
5540
 
    inc hl
5541
 
    ex de,hl
5542
 
    ld a,(de)
5543
 
    sub (hl)
5544
 
    ex de,hl
5545
 
    jr nc,$+5
5546
 
    ex de,hl
5547
 
    neg
5548
 
    cp 24
5549
 
    jp nc,add_unneeded
5550
 
    push hl
5551
 
    ld hl,addend+6
5552
 
    dec de
5553
 
    ld bc,0408h
5554
 
    dec hl
5555
 
    ld (hl),0
5556
 
    sub c
5557
 
    jr nc,$-5
5558
 
    add a,c
5559
 
    push af
5560
 
    push hl
5561
 
    ex de,hl
5562
 
    ld a,(hl)
5563
 
    or 80h
5564
 
    ld (de),a
5565
 
    dec de
5566
 
    dec hl
5567
 
    ldd
5568
 
    ldd
5569
 
    ex de,hl
5570
 
    dec b
5571
 
    jr z,$+7
5572
 
    ld (hl),0
5573
 
    dec hl
5574
 
    djnz $-3
5575
 
    pop hl
5576
 
    pop af
5577
 
    ld b,a
5578
 
    jr z,noshift
5579
 
    set 7,(hl)
5580
 
_1:
5581
 
    push hl
5582
 
    srl (hl)
5583
 
    dec hl
5584
 
    rr (hl)
5585
 
    dec hl
5586
 
    rr (hl)
5587
 
    dec hl
5588
 
    rr (hl)
5589
 
    pop hl
5590
 
    djnz _1
5591
 
noshift:
5592
 
    pop hl  ;bigger float
5593
 
    dec hl
5594
 
    ld b,(hl)
5595
 
    dec hl
5596
 
    dec hl
5597
 
    ex de,hl
5598
 
    pop af
5599
 
    jp m,subtract
5600
 
    ld hl,addend+2
5601
 
    ld a,(hl)
5602
 
    rla
5603
 
    inc hl
5604
 
    ld a,(de)
5605
 
    adc a,(hl)
5606
 
    ld (hl),a
5607
 
    inc hl
5608
 
    inc de
5609
 
    ld a,(de)
5610
 
    adc a,(hl)
5611
 
    ld (hl),a
5612
 
    inc hl
5613
 
    inc de
5614
 
    ld a,(de)
5615
 
    set 7,a
5616
 
    adc a,(hl)
5617
 
    ld (hl),a
5618
 
    inc hl
5619
 
    inc de
5620
 
    ld a,(de)
5621
 
    ld (hl),a
5622
 
    jp nc,add_done
5623
 
    inc (hl)
5624
 
    jp z,add_overflow
5625
 
    dec hl
5626
 
    rr (hl)
5627
 
    dec hl
5628
 
    rr (hl)
5629
 
    dec hl
5630
 
    rr (hl)
5631
 
    jp add_done
5632
 
subtract:
5633
 
    ld hl,addend
5634
 
    xor a
5635
 
    ld c,a
5636
 
    sub (hl)
5637
 
    ld (hl),a
5638
 
    inc hl
5639
 
    ld a,c
5640
 
    sbc a,(hl)
5641
 
    ld (hl),a
5642
 
    inc hl
5643
 
    ld a,c
5644
 
    sbc a,(hl)
5645
 
    ld (hl),a
5646
 
    inc hl
5647
 
    ld a,(de)
5648
 
    sbc a,(hl)
5649
 
    ld (hl),a
5650
 
    inc hl
5651
 
    inc de
5652
 
    ld a,(de)
5653
 
    sbc a,(hl)
5654
 
    ld (hl),a
5655
 
    inc hl
5656
 
    inc de
5657
 
    ld a,(de)
5658
 
    set 7,a
5659
 
    sbc a,(hl)
5660
 
    ld (hl),a
5661
 
    inc hl
5662
 
    inc de
5663
 
    ld a,(de)
5664
 
    ld (hl),a
5665
 
    dec de
5666
 
    ex de,hl
5667
 
    jr nc,negated
5668
 
    ld hl,addend
5669
 
    ld a,80h
5670
 
    xor b
5671
 
    ld b,a
5672
 
    ld a,c
5673
 
    sub (hl)
5674
 
    ld (hl),a
5675
 
    inc hl
5676
 
    ld a,c
5677
 
    sbc a,(hl)
5678
 
    ld (hl),a
5679
 
    inc hl
5680
 
    ld a,c
5681
 
    sbc a,(hl)
5682
 
    ld (hl),a
5683
 
    inc hl
5684
 
    ld a,c
5685
 
    sbc a,(hl)
5686
 
    ld (hl),a
5687
 
    inc hl
5688
 
    ld a,c
5689
 
    sbc a,(hl)
5690
 
    ld (hl),a
5691
 
    inc hl
5692
 
    ld a,c
5693
 
    sbc a,(hl)
5694
 
    ld (hl),a
5695
 
negated:
5696
 
    jp m,add_done
5697
 
    push bc
5698
 
    ld hl,(addend)
5699
 
    ld de,(addend+2)
5700
 
    ld bc,(addend+4)
5701
 
    ld a,h
5702
 
    or l
5703
 
    or d
5704
 
    or e
5705
 
    or b
5706
 
    or c
5707
 
    jp z,add_underflow
5708
 
    ld a,(addend+6)
5709
 
normalize:
5710
 
    dec a
5711
 
    jr z,add_underflow
5712
 
    add hl,hl
5713
 
    rl e
5714
 
    rl d
5715
 
    rl c
5716
 
    rl b
5717
 
    jp p,normalize
5718
 
    ld (addend),hl
5719
 
    ld (addend+2),de
5720
 
    ld (addend+4),bc
5721
 
    ld (addend+6),a
5722
 
    pop bc
5723
 
add_done:
5724
 
;;Need to adjust sign flag
5725
 
    ld hl,addend+5
5726
 
    ld a,(hl)
5727
 
    rla
5728
 
    rl b
5729
 
    rra
5730
 
    ld (hl),a
5731
 
    dec hl
5732
 
    dec hl
5733
 
add_copy:
5734
 
    pop de
5735
 
    push de
5736
 
    ldi
5737
 
    ldi
5738
 
    ldi
5739
 
    ld a,(hl)
5740
 
    ld (de),a
5741
 
    pop bc
5742
 
    pop de
5743
 
    pop hl
5744
 
    pop af
5745
 
    ret
5746
 
add_underflow:
5747
 
;;How many push/pops are needed?
5748
 
;;return ZERO
5749
 
    ld hl,0
5750
 
    ld (addend+3),hl
5751
 
    ld (addend+5),hl
5752
 
    pop bc
5753
 
    jr add_done
5754
 
add_overflow:
5755
 
;;How many push/pops are needed?
5756
 
;;return INF
5757
 
    dec hl
5758
 
    ld (hl),40h
5759
 
    jr add_done
5760
 
add_unneeded:
5761
 
;;How many push/pops are needed?
5762
 
;;Return bigger number
5763
 
    pop af
5764
 
    dec hl
5765
 
    dec hl
5766
 
    dec hl
5767
 
    jr add_copy
5768
 
 
5769
 
;---------------------------------------------------------------------------------------------------------
5770
 
; subSingle
5771
 
;---------------------------------------------------------------------------------------------------------
5772
 
 
5773
 
subSingle:
5774
 
;;x-y
5775
 
    push af
5776
 
    push hl
5777
 
    push de
5778
 
    push bc
5779
 
    push hl
5780
 
    ex de,hl
5781
 
    ld de,addend2
5782
 
    ldi
5783
 
    ldi
5784
 
    ld a,(hl)
5785
 
    xor 80h
5786
 
    ld (de),a
5787
 
    inc de
5788
 
    inc hl
5789
 
    ld a,(hl)
5790
 
    ld (de),a
5791
 
    ex de,hl
5792
 
    pop hl
5793
 
    ld de,addend2
5794
 
    jp addInject    ;jumps in to the addSingle routine
5795
 
 
5796
 
;---------------------------------------------------------------------------------------------------------
5797
 
; mulSingle
5798
 
;---------------------------------------------------------------------------------------------------------
5799
 
 
5800
 
mulSingle:
5801
 
;Inputs: HL points to float1, DE points to float2, BC points to where the result is copied
5802
 
;Outputs: float1*float2 is stored to (BC)
5803
 
;573+mul24+{0,35}+{0,30}
5804
 
;min: 1398cc
5805
 
;max: 2564cc
5806
 
;avg: 2055.13839751681cc
5807
 
    push af
5808
 
    push hl
5809
 
    push de
5810
 
    push bc
5811
 
 
5812
 
    call _2   ;CHLB
5813
 
    ld a,c
5814
 
    ex de,hl
5815
 
    pop hl
5816
 
    push hl
5817
 
    ld (hl),b
5818
 
    inc hl
5819
 
    ld (hl),e
5820
 
    inc hl
5821
 
    ld (hl),d
5822
 
    inc hl
5823
 
    ld (hl),a
5824
 
    pop bc
5825
 
    pop de
5826
 
    pop hl
5827
 
    pop af
5828
 
    ret
5829
 
 
5830
 
 
5831
 
_2:
5832
 
;;return float in CHLB
5833
 
    push de
5834
 
    ld e,(hl)
5835
 
    inc hl
5836
 
    ld d,(hl)
5837
 
    inc hl
5838
 
    ld c,(hl)
5839
 
    inc hl
5840
 
    ld a,(hl)
5841
 
    or a
5842
 
    jr z,mulSingle_case0
5843
 
    ex de,hl
5844
 
    ex (sp),hl
5845
 
    ld e,(hl)
5846
 
    inc hl
5847
 
    ld d,(hl)
5848
 
    inc hl
5849
 
    ld b,(hl)
5850
 
    inc hl
5851
 
 
5852
 
    ;inc (hl)
5853
 
    ;dec (hl)
5854
 
    ;jr z,mulSingle_case1
5855
 
    push af
5856
 
    ld a, (hl)
5857
 
    or a
5858
 
    jp z,mulSingle_case1
5859
 
    pop af
5860
 
 
5861
 
    add a,(hl)      ;\
5862
 
    pop hl          ; |
5863
 
    rra             ; |Lots of help from Runer112 and
5864
 
    adc a,a         ; |calc84maniac for optimizing
5865
 
    jp po,bad       ; |this exponent check.
5866
 
    xor 80h         ; |
5867
 
    jr z,underflow  ;/
5868
 
    push af         ;exponent
5869
 
    ld a,b
5870
 
    xor c
5871
 
    push af         ;sign
5872
 
    set 7,b
5873
 
    set 7,c
5874
 
    call mul24      ;BDE*CHL->HLBCDE, returns sign info
5875
 
    pop de
5876
 
    ld a,e
5877
 
    pop de
5878
 
    jp m,_3
5879
 
    rl c
5880
 
    rl b
5881
 
    adc hl,hl
5882
 
    dec d
5883
 
_3:
5884
 
    inc d
5885
 
    jr z,overflow
5886
 
    rl c
5887
 
    ld c,d
5888
 
    ld de,0
5889
 
    push af
5890
 
    ld a,b
5891
 
    adc a,e
5892
 
    ld b,a
5893
 
    adc hl,de
5894
 
    jr nc,_4
5895
 
    inc c
5896
 
    jr z,overflow
5897
 
    rr h
5898
 
    rr l
5899
 
    rr b
5900
 
_4:
5901
 
    pop af
5902
 
    cpl
5903
 
    and $80
5904
 
    xor h
5905
 
    ld h,a
5906
 
    ret
5907
 
bad:
5908
 
    jr nc,overflow
5909
 
underflow:
5910
 
    ld hl,0
5911
 
    rl b
5912
 
    rr h
5913
 
    ld c,l
5914
 
    ld b,l
5915
 
    ret
5916
 
overflow:
5917
 
    ld hl,$8000
5918
 
    jr underflow+3
5919
 
mulSingle_case1:
5920
 
;x*0   -> 0
5921
 
;x*inf -> inf
5922
 
;x*NaN -> NaN
5923
 
  pop af
5924
 
  pop hl
5925
 
  ld h,b
5926
 
  ld l,d
5927
 
  ld b,e
5928
 
  ld c,0
5929
 
  ret
5930
 
mulSingle_case0:
5931
 
;special*x = special
5932
 
;NaN*x = NaN
5933
 
;0*0 = 0
5934
 
;0*NaN = NaN
5935
 
;0*Inf = NaN
5936
 
;Inf*Inf  = Inf
5937
 
;Inf*-Inf =-Inf
5938
 
  ;0CDE
5939
 
  pop hl
5940
 
  inc hl
5941
 
  inc hl
5942
 
  inc hl
5943
 
  ld a,(hl)
5944
 
  or a
5945
 
  jr z,_5
5946
 
  ld h,c
5947
 
  ld c,0
5948
 
  ret
5949
 
_5:
5950
 
  dec hl
5951
 
  ld b,(hl)
5952
 
;basically, if b|c has bit 5 set, return NaN
5953
 
  ld a,b
5954
 
  or c
5955
 
  ld h,$20
5956
 
  and h
5957
 
  jr z,_6
5958
 
  ld c,0
5959
 
  ret
5960
 
_6:
5961
 
  ld a,c
5962
 
  xor b
5963
 
  rl b
5964
 
  rlca
5965
 
  rr b
5966
 
  res 4,b
5967
 
 
5968
 
  rl c
5969
 
  rrca
5970
 
  rr c
5971
 
 
5972
 
  ld a,c
5973
 
  and $E0
5974
 
  add a,b
5975
 
  rra
5976
 
  ld h,a
5977
 
  ld c,0
5978
 
  ret
5979
 
mul24:
5980
 
;;BDE*CHL -> HLBCDE
5981
 
;;155 bytes
5982
 
;;402+3*C_Times_BDE
5983
 
;;fastest:1201cc
5984
 
;;slowest:1753cc
5985
 
;;avg    :1464.9033203125cc (1464+925/1024)
5986
 
;min: 825cc
5987
 
;max: 1926cc
5988
 
;avg: 1449.63839751681cc
5989
 
 
5990
 
    push bc
5991
 
    ld c,l
5992
 
    push hl
5993
 
    call C_Times_BDE
5994
 
    ld (var48),hl
5995
 
    ld l,a
5996
 
    ld h,c
5997
 
    ld (var48+2),hl
5998
 
 
5999
 
    pop hl
6000
 
    ld c,h
6001
 
    call C_Times_BDE
6002
 
    push bc
6003
 
    ld bc,(var48+1)
6004
 
    add hl,bc
6005
 
    ld (var48+1),hl
6006
 
    pop bc
6007
 
    ld b,c
6008
 
    ld c,a
6009
 
    ld hl,(var48+3)
6010
 
    ld h,0
6011
 
    adc hl,bc
6012
 
    ld (var48+3),hl
6013
 
 
6014
 
    pop bc
6015
 
    call C_Times_BDE
6016
 
    ld de,(var48+2)
6017
 
    add hl,de
6018
 
    ld (var48+2),hl
6019
 
    ld d,c
6020
 
    ld e,a
6021
 
    ld b,h
6022
 
    ld c,l
6023
 
    ld hl,(var48+4)
6024
 
    ld h,0
6025
 
    adc hl,de
6026
 
    ld de,(var48)
6027
 
    ret
6028
 
 
6029
 
;---------------------------------------------------------------------------------------------------------
6030
 
; divSingle
6031
 
;---------------------------------------------------------------------------------------------------------
6032
 
 
6033
 
divSingle:
6034
 
;;HL points to numerator
6035
 
;;DE points to denominator
6036
 
;;BC points to where the quotient gets written
6037
 
  call pushpop
6038
 
divSingle_no_pushpop:
6039
 
    inc hl
6040
 
    inc de
6041
 
    inc hl
6042
 
    inc de
6043
 
    ld a,(de)   ;\
6044
 
    xor (hl)    ; |Get sign of output
6045
 
    add a,a     ; |
6046
 
    push af     ;/
6047
 
    push bc
6048
 
    inc hl
6049
 
    inc de
6050
 
    ld a,(hl)   ;\
6051
 
    ex de,hl    ; |Get exponent
6052
 
    sub (hl)    ; |
6053
 
    ex de,hl    ; |
6054
 
 
6055
 
    ld b,-1
6056
 
    jr nc,_7
6057
 
    dec b
6058
 
_7:
6059
 
    add a,128
6060
 
    jr nc,_8
6061
 
    inc b
6062
 
_8:
6063
 
    inc b
6064
 
    jr z,_9
6065
 
    jp p,divunderflow
6066
 
    jp m,divoverflow
6067
 
_9:
6068
 
    ld (quot+3),a
6069
 
    dec hl
6070
 
    dec de
6071
 
    ld b,(hl)
6072
 
    dec hl
6073
 
    ld a,(hl)
6074
 
    dec hl
6075
 
    ld l,(hl)
6076
 
    ld h,a
6077
 
    ex de,hl
6078
 
 
6079
 
    ld c,(hl)
6080
 
    dec hl
6081
 
    ld a,(hl)
6082
 
    dec hl
6083
 
    ld l,(hl)
6084
 
    ld h,a
6085
 
    ex de,hl
6086
 
 
6087
 
    set 7,c
6088
 
    ld a,b
6089
 
    or 80h
6090
 
    sbc hl,de
6091
 
    sbc a,c
6092
 
    jr nz,_10
6093
 
    or h
6094
 
    or l
6095
 
    jr z,setmantissa0
6096
 
    xor a
6097
 
_10:
6098
 
    jr nc,startdiv
6099
 
    ld b,a
6100
 
    ld a,(quot+3)
6101
 
    dec a
6102
 
    ld (quot+3),a
6103
 
    ld a,b
6104
 
    add hl,hl
6105
 
    adc a,a
6106
 
    add hl,de
6107
 
    adc a,c
6108
 
startdiv:
6109
 
    ld b,1
6110
 
    call divsub0+3
6111
 
    ld (quot+1),bc
6112
 
    call divsub0
6113
 
    ld (quot),bc
6114
 
    call divsub0
6115
 
    ld (quot-1),bc
6116
 
    add hl,hl
6117
 
    rla
6118
 
    jr c,_11
6119
 
    sbc hl,de
6120
 
    sbc a,c
6121
 
    ccf
6122
 
_11:
6123
 
    ld hl,(quot)
6124
 
    ld de,(quot+2)
6125
 
    ld bc,0
6126
 
    adc hl,bc
6127
 
    ex de,hl
6128
 
    adc hl,bc
6129
 
    ld b,h
6130
 
    ld c,l
6131
 
writeback:
6132
 
    pop hl
6133
 
    ld (hl),e
6134
 
    inc hl
6135
 
    ld (hl),d
6136
 
    inc hl
6137
 
    rl c
6138
 
    pop af
6139
 
    rr c
6140
 
    ld (hl),c
6141
 
    inc hl
6142
 
    ld (hl),b
6143
 
    ret
6144
 
divoverflow:
6145
 
    ld b,$40
6146
 
    jr _12
6147
 
divunderflow:
6148
 
  ld b,0
6149
 
  jr _12
6150
 
setmantissa0:
6151
 
  ld bc,(quot+2)
6152
 
_12:
6153
 
  ld de,0
6154
 
  ld c,e
6155
 
  jr writeback
6156
 
divsub0:
6157
 
;;882cc max
6158
 
    call divsub1    ;34 or 66
6159
 
    call divsub1    ;
6160
 
    call divsub1
6161
 
    call divsub1
6162
 
    call divsub1
6163
 
    call divsub1
6164
 
    call divsub1
6165
 
    call divsub1
6166
 
    or a
6167
 
    sbc hl,de
6168
 
    sbc a,c
6169
 
    inc b
6170
 
    ret nc
6171
 
    dec b
6172
 
    add hl,de
6173
 
    adc a,c
6174
 
    ret
6175
 
divsub1:
6176
 
;34cc or 66cc or 93cc
6177
 
    sla b
6178
 
    add hl,hl
6179
 
    rla
6180
 
    ret nc
6181
 
    or a
6182
 
    inc b
6183
 
    sbc hl,de
6184
 
    sbc a,c
6185
 
    ret c
6186
 
    inc b
6187
 
    sbc hl,de
6188
 
    sbc a,c
6189
 
    ret
6190
 
 
6191
 
;---------------------------------------------------------------------------------------------------------
6192
 
; powSingle
6193
 
; https://www.geeksforgeeks.org/write-a-c-program-to-calculate-powxn/
6194
 
; https://stackoverflow.com/questions/3518973/floating-point-exponentiation-without-power-function
6195
 
;---------------------------------------------------------------------------------------------------------
6196
 
;double mypow( double base, double power, double precision )
6197
 
;{
6198
 
;   if ( power < 0 ) return 1 / mypow( base, -power, precision );
6199
 
;   else if ( power >= 1 ) return base * mypow( base, power-1, precision );
6200
 
;   else if ( precision >= 1 ) {
6201
 
;          if( base >= 0 ) return sqrt( base );
6202
 
;          else return sqrt( -base );
6203
 
;   } else return sqrt( mypow( base, power*2, precision*2 ) );
6204
 
;}
6205
 
 
6206
 
if defined MATH.POW or defined MATH_EXP or defined MATH_LOG or defined MATH_LN
6207
 
 
6208
 
powSingle:
6209
 
;;Computes y^x
6210
 
;;HL points to y
6211
 
;;DE points to x
6212
 
;;BC points to output
6213
 
    call pushpop
6214
 
    push bc
6215
 
      push de
6216
 
            ld bc, var_y     ; power
6217
 
            call copySingle
6218
 
          pop hl
6219
 
          ld bc, var_x       ; base
6220
 
          call copySingle
6221
 
          ld hl, const_precision
6222
 
          ld bc, var_a       ; precision
6223
 
          call copySingle
6224
 
          ld hl, const_0
6225
 
          ld bc, var_z       ; result
6226
 
          call copySingle
6227
 
          call powSingle.loop
6228
 
        pop bc
6229
 
        ld hl, var_z
6230
 
        call copySingle
6231
 
        ret
6232
 
 
6233
 
powSingle.loop:
6234
 
;   if ( power < 0 ) return 1 / mypow( base, -power, precision );
6235
 
    ld hl, var_y
6236
 
        ld de, const_0
6237
 
        call cmpSingle
6238
 
        jp c, powSingle.1
6239
 
 
6240
 
;   else if ( power >= 1 ) return base * mypow( base, power-1, precision );
6241
 
    ld hl, var_y
6242
 
        ld de, const_1
6243
 
        call cmpSingle
6244
 
        jp nc, powSingle.2
6245
 
 
6246
 
;   else if ( precision >= 1 ) {
6247
 
;          if( base >= 0 ) return sqrt( base );
6248
 
;          else return sqrt( -base );
6249
 
    ld hl, var_a
6250
 
        ld de, const_1
6251
 
        call cmpSingle
6252
 
        jp nc, powSingle.3
6253
 
 
6254
 
;   } else return sqrt( mypow( base, power*2, precision*2 ) );
6255
 
    ld hl, var_y
6256
 
        ld de, const_2
6257
 
        ld bc, var_b
6258
 
        call mulSingle
6259
 
        ld hl, var_b
6260
 
        ld bc, var_y
6261
 
        call copySingle
6262
 
    ld hl, var_a
6263
 
        ld de, const_2
6264
 
        ld bc, var_b
6265
 
        call mulSingle
6266
 
        ld hl, var_b
6267
 
        ld bc, var_a
6268
 
        call copySingle
6269
 
        call powSingle.loop
6270
 
        ld hl, var_z
6271
 
        ld bc, var_b
6272
 
        call sqrtSingle
6273
 
        ld hl, var_b
6274
 
        ld bc, var_z
6275
 
        call copySingle
6276
 
        ret
6277
 
 
6278
 
powSingle.1:
6279
 
; return 1 / mypow( base, -power, precision );
6280
 
    ld hl, const_0
6281
 
        ld de, var_y
6282
 
        ld bc, var_b
6283
 
        call subSingle
6284
 
        ld hl, var_b
6285
 
        ld bc, var_y
6286
 
        call copySingle
6287
 
        call powSingle.loop
6288
 
        ld hl, const_1
6289
 
        ld de, var_z
6290
 
        ld bc, var_b
6291
 
        call divSingle
6292
 
        ld hl, var_b
6293
 
        ld bc, var_z
6294
 
        call copySingle
6295
 
    ret
6296
 
 
6297
 
powSingle.2:
6298
 
; return base * mypow( base, power-1, precision );
6299
 
    ld hl, var_y
6300
 
        ld de, const_1
6301
 
        ld bc, var_b
6302
 
        call subSingle
6303
 
        ld hl, var_b
6304
 
        ld bc, var_y
6305
 
        call copySingle
6306
 
        call powSingle.loop
6307
 
        ld hl, var_z
6308
 
        ld de, var_x
6309
 
        ld bc, var_b
6310
 
        call mulSingle
6311
 
        ld hl, var_b
6312
 
        ld bc, var_z
6313
 
        call copySingle
6314
 
    ret
6315
 
 
6316
 
powSingle.3:
6317
 
;          if( base >= 0 ) return sqrt( base );
6318
 
;          else return sqrt( -base );
6319
 
    ld hl, var_x
6320
 
        ld de, const_0
6321
 
        call cmpSingle
6322
 
        jp nc, powSingle.1
6323
 
        ;ld hl, var_x
6324
 
        ld bc, var_b
6325
 
        call negSingle
6326
 
        ld hl, var_b
6327
 
        ;ld bc, var_z
6328
 
        ;call sqrtSingle
6329
 
        ;ret
6330
 
 
6331
 
powSingle.3.1:
6332
 
    ;ld hl, var_x
6333
 
        ld bc, var_z
6334
 
        call sqrtSingle
6335
 
    ret
6336
 
 
6337
 
pow2Single:
6338
 
;;Computes 2^x
6339
 
  call pushpop
6340
 
  push bc
6341
 
 
6342
 
exp_inject:
6343
 
;if x is on [0,1):
6344
 
;  2^x = 1.000000001752 + x * (0.693146989552 + x * (0.2402298085906 + x * (5.54833215071e-2 + x * (9.67907584392e-3 + x * (1.243632065103e-3 + x * 2.171671843714e-4)))))
6345
 
;Please note that usually I like to reduce to [-.5,.5] as the extra overhead is usually worth it.
6346
 
;In this case, our polynomial is the same degree, with error different by less than 1 bit, so it's just a waste to range-reduce in this way.
6347
 
;
6348
 
;int(x) -> out_exp
6349
 
;x-=int(x)  ;leaves x in [0,1)
6350
 
;;If x==0    -> out==1
6351
 
;;if x==inf  -> out==inf
6352
 
;;if x==-inf -> out==0
6353
 
;;if x==NAN  -> out==NAN
6354
 
  ld de,var48+10
6355
 
  call mov4
6356
 
  ld hl,(var48+10)
6357
 
  ld de,(var48+12)
6358
 
  ld a,e
6359
 
  add a,a
6360
 
  push af   ;keep track of sign
6361
 
  rrca
6362
 
  ld (var48+12),a
6363
 
  ld c,a
6364
 
  ld a,d
6365
 
    or a
6366
 
    jp z,exp_spec
6367
 
    cp 80h-23
6368
 
    jp c,exp_underflow
6369
 
    sub 128   ; sub a,128
6370
 
    jr c,_pow_1 ;int(x)=0
6371
 
    inc a
6372
 
    cp 7
6373
 
    jp nc,exp_overflow
6374
 
    set 7,c
6375
 
    ld b,a
6376
 
    xor a
6377
 
    add hl,hl
6378
 
    rl c
6379
 
    rla
6380
 
    djnz $-4
6381
 
    ld b,7Fh
6382
 
    bit 7,c
6383
 
    jr nz,exp_normalized
6384
 
    ld e,a
6385
 
    ld a,h
6386
 
    or l
6387
 
    or c
6388
 
    ld a,e
6389
 
    jr z,exp_zeroed
6390
 
    dec b
6391
 
    add hl,hl
6392
 
    rl c
6393
 
    jp p,$-4
6394
 
    jr exp_normalized  ;.db $11 ;start of `ld de,**`
6395
 
exp_zeroed:
6396
 
    ld b,0
6397
 
exp_normalized:
6398
 
    ld (var48+10),hl
6399
 
    res 7,c
6400
 
    ld (var48+12),bc
6401
 
    jr comp_exp   ;.db $06 ;start of 'ld b,*` just to eat the next byte
6402
 
_pow_1:
6403
 
    xor a
6404
 
comp_exp:
6405
 
  pop hl
6406
 
  rr l
6407
 
  jr nc,_pow_2
6408
 
  cpl
6409
 
  or a
6410
 
  jp z,exp_underflow+1
6411
 
  ;perform 1-(var48+10)--> var48+10
6412
 
  ld hl,const_1
6413
 
  ld de,var48+10
6414
 
  ld b,d
6415
 
  ld c,e
6416
 
  call subSingle
6417
 
_pow_2:
6418
 
  push af
6419
 
;our 'x' is at var48+10
6420
 
;our `temp` is at var48+6 so as not to cause issues with mulSingle)
6421
 
;uses 14 bytes of RAM
6422
 
  ld hl,var48+10
6423
 
  ld de,exp_a6
6424
 
  ld bc,var48+6
6425
 
  call mulSingle
6426
 
  ld d,b
6427
 
  ld e,c
6428
 
  ld hl,exp_a5
6429
 
  call addSingle
6430
 
  ld hl,var48+10
6431
 
  call mulSingle
6432
 
  ld hl,exp_a4
6433
 
  call addSingle
6434
 
  ld hl,var48+10
6435
 
  call mulSingle
6436
 
  ld hl,exp_a3
6437
 
  call addSingle
6438
 
  ld hl,var48+10
6439
 
  call mulSingle
6440
 
  ld hl,exp_a2
6441
 
  call addSingle
6442
 
  ld hl,var48+10
6443
 
  call mulSingle
6444
 
  ld hl,exp_a1
6445
 
  call addSingle
6446
 
  ld hl,var48+10
6447
 
  call mulSingle
6448
 
  ld hl,const_1
6449
 
  call addSingle
6450
 
  ld hl,var48+9
6451
 
  pop af
6452
 
  add a,(hl)
6453
 
  ld (hl),a
6454
 
  ex de,hl
6455
 
  pop de
6456
 
  jp mov4
6457
 
exp_spec:
6458
 
;bit 6 means INF
6459
 
;bit 5 means NAN
6460
 
;no bits means zero
6461
 
;NAN -> NAN
6462
 
;+inf -> +inf
6463
 
;-inf -> +0  because lim approaches 0 from the right
6464
 
    ld a,c
6465
 
    add a,a
6466
 
    jr z,exp_zero
6467
 
    jp m,exp_inf
6468
 
;exp_NAN
6469
 
    pop af
6470
 
    ld de,0040h
6471
 
exp_return_spec:
6472
 
    pop hl
6473
 
    rr e
6474
 
    ld (hl),a
6475
 
    inc hl
6476
 
    ld (hl),a
6477
 
    inc hl
6478
 
    ld (hl),e
6479
 
    inc hl
6480
 
    ld (hl),d
6481
 
    ret
6482
 
exp_overflow:
6483
 
exp_inf:
6484
 
;+inf -> +inf
6485
 
;-inf -> +0  because lim approaches 0 from the right
6486
 
    pop af
6487
 
    sbc a,a ;FF if should be 0,
6488
 
    cpl
6489
 
    and 80h
6490
 
    ld d,0
6491
 
    ld e,a
6492
 
    jr exp_return_spec
6493
 
exp_underflow:
6494
 
exp_zero:
6495
 
    pop af
6496
 
    or a
6497
 
    ld de,$8000
6498
 
    jr exp_return_spec
6499
 
 
6500
 
endif
6501
 
 
6502
 
;---------------------------------------------------------------------------------------------------------
6503
 
; sqrtSingle
6504
 
;---------------------------------------------------------------------------------------------------------
6505
 
 
6506
 
if defined MATH_SQR or defined MATH_EXP
6507
 
 
6508
 
;Uses 3 bytes at scrap
6509
 
sqrtSingle:
6510
 
;552+{0,19}+8{0,3+{0,3}}+pushpop+sqrtHLIX
6511
 
;min: 1784
6512
 
;max: 1987
6513
 
;avg: 1872
6514
 
  call pushpop
6515
 
  push bc
6516
 
  ld c,(hl)
6517
 
  inc hl
6518
 
  ld e,(hl)
6519
 
  inc hl
6520
 
  ld a,(hl)
6521
 
  add a,a
6522
 
  jp c,sqrtSingle_NaN
6523
 
  scf
6524
 
  rra
6525
 
  ld d,a
6526
 
  inc hl
6527
 
  ld a,(hl)
6528
 
  or a
6529
 
  jp z,sqrtSingle_special
6530
 
  add a,80h
6531
 
  rra
6532
 
  push af   ;new exponent
6533
 
  jr c,_13
6534
 
  srl d
6535
 
  rr e
6536
 
  rr c
6537
 
_13:
6538
 
  ex de,hl
6539
 
  ld ixh,c
6540
 
  ld ixl,0
6541
 
  call sqrtHLIX
6542
 
;AHL is the new remainder
6543
 
;Need to divide by 2, then divide by the 16-bit (var_x+4)
6544
 
  rra
6545
 
  ld a,h
6546
 
;HL/DE to 8 bits
6547
 
;We are just going to approximate it
6548
 
  res 0,l
6549
 
  jr c,$+5
6550
 
  cp d
6551
 
  jr c,$+4
6552
 
  sub d
6553
 
  inc l
6554
 
  sla l
6555
 
  rla
6556
 
  jr c,$+5
6557
 
  cp d
6558
 
  jr c,$+4
6559
 
  sub d
6560
 
  inc l
6561
 
  sla l
6562
 
  rla
6563
 
  jr c,$+5
6564
 
  cp d
6565
 
  jr c,$+4
6566
 
  sub d
6567
 
  inc l
6568
 
  sla l
6569
 
  rla
6570
 
  jr c,$+5
6571
 
  cp d
6572
 
  jr c,$+4
6573
 
  sub d
6574
 
  inc l
6575
 
  sla l
6576
 
  rla
6577
 
  jr c,$+5
6578
 
  cp d
6579
 
  jr c,$+4
6580
 
  sub d
6581
 
  inc l
6582
 
  sla l
6583
 
  rla
6584
 
  jr c,$+5
6585
 
  cp d
6586
 
  jr c,$+4
6587
 
  sub d
6588
 
  inc l
6589
 
  sla l
6590
 
  rla
6591
 
  jr c,$+5
6592
 
  cp d
6593
 
  jr c,$+4
6594
 
  sub d
6595
 
  inc l
6596
 
  sla l
6597
 
  rla
6598
 
  jr c,$+5
6599
 
  cp d
6600
 
  jr c,$+4
6601
 
  sub d
6602
 
  inc l
6603
 
 
6604
 
  pop bc
6605
 
  ld a,l
6606
 
  pop hl
6607
 
  ;BDEA
6608
 
  ld (hl),a
6609
 
  inc hl
6610
 
  ld (hl),e
6611
 
  inc hl
6612
 
  res 7,d
6613
 
  ld (hl),d
6614
 
  inc hl
6615
 
  ld (hl),b
6616
 
  ret
6617
 
sqrtSingle_NaN:
6618
 
  ld hl,const_NaN
6619
 
  pop de
6620
 
  jp mov4
6621
 
sqrtSingle_special:
6622
 
  dec hl
6623
 
  dec hl
6624
 
  pop de
6625
 
  jp mov4
6626
 
 
6627
 
sqrtHLIX:
6628
 
;Input: HLIX
6629
 
;Output: DE is the sqrt, AHL is the remainder
6630
 
;speed: 754+{0,1}+6{0,6}+{0,3+{0,18}}+{0,38}+sqrtHL
6631
 
;min: 1130
6632
 
;max: 1266
6633
 
;avg: 1190.5
6634
 
 
6635
 
 
6636
 
  call sqrtHL
6637
 
  add a,a
6638
 
  ld e,a
6639
 
  jr nc,_14
6640
 
  inc d
6641
 
_14:
6642
 
 
6643
 
  ld a,ixh
6644
 
  sll e
6645
 
  rl d
6646
 
  add a,a
6647
 
  adc hl,hl
6648
 
  add a,a
6649
 
  adc hl,hl
6650
 
  sbc hl,de
6651
 
  jr nc,_15
6652
 
  add hl,de
6653
 
  dec e
6654
 
  jr _15a      ;.db $FE     ;start of `cp *`
6655
 
_15:
6656
 
  inc e
6657
 
_15a:
6658
 
  sll e
6659
 
  rl d
6660
 
  add a,a
6661
 
  adc hl,hl
6662
 
  add a,a
6663
 
  adc hl,hl
6664
 
  sbc hl,de
6665
 
  jr nc,_16
6666
 
  add hl,de
6667
 
  dec e
6668
 
  jr _16a   ;.db $FE     ;start of `cp *`
6669
 
_16:
6670
 
  inc e
6671
 
_16a:
6672
 
  sll e
6673
 
  rl d
6674
 
  add a,a
6675
 
  adc hl,hl
6676
 
  add a,a
6677
 
  adc hl,hl
6678
 
  sbc hl,de
6679
 
  jr nc,_17
6680
 
  add hl,de
6681
 
  dec e
6682
 
  jr _17a  ;.db $FE     ;start of `cp *`
6683
 
_17:
6684
 
  inc e
6685
 
_17a:
6686
 
  sll e
6687
 
  rl d
6688
 
  add a,a
6689
 
  adc hl,hl
6690
 
  add a,a
6691
 
  adc hl,hl
6692
 
  sbc hl,de
6693
 
  jr nc,_18
6694
 
  add hl,de
6695
 
  dec e
6696
 
  jr _18a  ;.db $FE     ;start of `cp *`
6697
 
_18:
6698
 
  inc e
6699
 
_18a:
6700
 
;Now we have four more iterations
6701
 
;The first two are no problem
6702
 
  ld a,ixl
6703
 
  sll e
6704
 
  rl d
6705
 
  add a,a
6706
 
  adc hl,hl
6707
 
  add a,a
6708
 
  adc hl,hl
6709
 
  sbc hl,de
6710
 
  jr nc,_19
6711
 
  add hl,de
6712
 
  dec e
6713
 
  jr _19a  ;.db $FE     ;start of `cp *`
6714
 
_19:
6715
 
  inc e
6716
 
_19a:
6717
 
  sll e
6718
 
  rl d
6719
 
  add a,a
6720
 
  adc hl,hl
6721
 
  add a,a
6722
 
  adc hl,hl
6723
 
  sbc hl,de
6724
 
  jr nc,_20
6725
 
  add hl,de
6726
 
  dec e
6727
 
  jr _20a  ;.db $FE     ;start of `cp *`
6728
 
_20:
6729
 
  inc e
6730
 
_20a:
6731
 
sqrt32_iter15:
6732
 
;On the next iteration, HL might temporarily overflow by 1 bit
6733
 
  sll e
6734
 
  rl d      ;sla e \ rl d \ inc e
6735
 
  add a,a
6736
 
  adc hl,hl
6737
 
  add a,a
6738
 
  adc hl,hl       ;This might overflow!
6739
 
  jr c,sqrt32_iter15_br0
6740
 
;
6741
 
  sbc hl,de
6742
 
  jr nc,_21
6743
 
  add hl,de
6744
 
  dec e
6745
 
  jr sqrt32_iter16
6746
 
sqrt32_iter15_br0:
6747
 
  or a
6748
 
  sbc hl,de
6749
 
_21:
6750
 
  inc e
6751
 
 
6752
 
;On the next iteration, HL is allowed to overflow, DE could overflow with our current routine, but it needs to be shifted right at the end, anyways
6753
 
sqrt32_iter16:
6754
 
  add a,a
6755
 
  ld b,a        ;either 0x00 or 0x80
6756
 
  adc hl,hl
6757
 
  rla
6758
 
  adc hl,hl
6759
 
  rla
6760
 
;AHL - (DE+DE+1)
6761
 
  sbc hl,de
6762
 
  sbc a,b
6763
 
  inc e
6764
 
  or a
6765
 
  sbc hl,de
6766
 
  sbc a,b
6767
 
  ret p
6768
 
  add hl,de
6769
 
  adc a,b
6770
 
  dec e
6771
 
  add hl,de
6772
 
  adc a,b
6773
 
  ret
6774
 
 
6775
 
sqrtHL:
6776
 
;returns A as the sqrt, HL as the remainder, D = 0
6777
 
;min: 376cc
6778
 
;max: 416cc
6779
 
;avg: 393cc
6780
 
  ld de,$5040
6781
 
  ld a,h
6782
 
  sub e
6783
 
  jr nc,_22
6784
 
  add a,e
6785
 
  ld d,$10
6786
 
_22:
6787
 
  sub d
6788
 
  jr nc,_23
6789
 
  add a,d
6790
 
  jr _23a  ;.db $01   ;start of ld bc,** which is 10cc to skip the next two bytes.
6791
 
_23:
6792
 
  set 5,d
6793
 
_23a:
6794
 
  res 4,d
6795
 
  srl d
6796
 
 
6797
 
  set 2,d
6798
 
  sub d
6799
 
  jr nc,_24
6800
 
  add a,d
6801
 
  jr _24a  ;.db $01   ;start of ld bc,** which is 10cc to skip the next two bytes.
6802
 
_24:
6803
 
  set 3,d
6804
 
_24a:
6805
 
  res 2,d
6806
 
  srl d
6807
 
 
6808
 
  inc d
6809
 
  sub d
6810
 
  jr nc,_25
6811
 
  add a,d
6812
 
  dec d   ;this resets the low bit of D, so `srl d` resets carry.
6813
 
  jr _25a  ;.db $06   ;start of ld b,* which is 7cc to skip the next byte.
6814
 
_25:
6815
 
  inc d
6816
 
_25a:
6817
 
  srl d
6818
 
  ld h,a
6819
 
 
6820
 
 
6821
 
  sbc hl,de
6822
 
  ld a,e
6823
 
  jr nc,_26
6824
 
  add hl,de
6825
 
_26:
6826
 
  ccf
6827
 
  rra
6828
 
  srl d
6829
 
  rra
6830
 
  ld e,a
6831
 
 
6832
 
  sbc hl,de
6833
 
  jr nc,_27
6834
 
  add hl,de
6835
 
  jr _27a  ;.db $01   ;start of ld bc,** which is 10cc to skip the next two bytes.
6836
 
_27:
6837
 
  or %00100000
6838
 
_27a:
6839
 
  xor %00011000
6840
 
  srl d
6841
 
  rra
6842
 
  ld e,a
6843
 
 
6844
 
 
6845
 
  sbc hl,de
6846
 
  jr nc,_28
6847
 
  add hl,de
6848
 
  jr _28a  ;.db $01   ;start of ld bc,** which is 10cc to skip the next two bytes.
6849
 
_28:
6850
 
  or %00001000
6851
 
_28a:
6852
 
  xor %00000110
6853
 
  srl d
6854
 
  rra
6855
 
  ld e,a
6856
 
  sbc hl,de
6857
 
  jr nc,_29
6858
 
  add hl,de
6859
 
  srl d
6860
 
  rra
6861
 
  ret
6862
 
_29:
6863
 
  inc a
6864
 
  srl d
6865
 
  rra
6866
 
  ret
6867
 
 
6868
 
endif
6869
 
 
6870
 
;---------------------------------------------------------------------------------------------------------
6871
 
; lnSingle
6872
 
;---------------------------------------------------------------------------------------------------------
6873
 
 
6874
 
if defined MATH_LOG or defined MATH_LN
6875
 
 
6876
 
lnSingle:
6877
 
; x / (1 + x/(2-x+4x/(3-2x+9x/(4-3x+16x/(5-4x)))))
6878
 
; a * x ^ (1/a) - a, where a = 100
6879
 
  call pushpop
6880
 
  push bc
6881
 
    ld de, const_100_inv
6882
 
        ld bc, temp
6883
 
        call powSingle         ; temp = x ^ (1/100)
6884
 
        ld hl, temp
6885
 
        ld de, const_100
6886
 
        ld bc, temp1
6887
 
        call mulSingle         ; temp1 = temp * 100
6888
 
        ld hl, temp1
6889
 
  pop bc
6890
 
  call subSingle           ; bc = temp1 - 100
6891
 
  ret
6892
 
 
6893
 
endif
6894
 
 
6895
 
;---------------------------------------------------------------------------------------------------------
6896
 
; logSingle
6897
 
;---------------------------------------------------------------------------------------------------------
6898
 
 
6899
 
if defined MATH_LOG
6900
 
 
6901
 
logSingle:
6902
 
  call pushpop
6903
 
  push bc
6904
 
    ld bc, temp
6905
 
    call lnSingle
6906
 
    ld hl, temp
6907
 
    ld de, const_lg10
6908
 
  pop bc
6909
 
  call divSingle
6910
 
  ret
6911
 
 
6912
 
endif
6913
 
 
6914
 
;---------------------------------------------------------------------------------------------------------
6915
 
; expSingle
6916
 
;---------------------------------------------------------------------------------------------------------
6917
 
 
6918
 
if defined MATH_EXP
6919
 
 
6920
 
expSingle:
6921
 
;;Computes e^x
6922
 
;;HL points to x
6923
 
;;BC points to the output
6924
 
  call pushpop
6925
 
  ld de,const_lg_e
6926
 
  push bc
6927
 
pow_inject:
6928
 
;;DE points to lg(y), HL points to x, BC points to output
6929
 
  ld bc,var_x
6930
 
  call mulSingle
6931
 
  ld h,b
6932
 
  ld l,c
6933
 
  jp exp_inject
6934
 
 
6935
 
endif
6936
 
 
6937
 
;---------------------------------------------------------------------------------------------------------
6938
 
; sinSingle
6939
 
; https://en.wikipedia.org/wiki/List_of_trigonometric_identities
6940
 
; https://en.wikipedia.org/wiki/Taylor_series#Trigonometric_functions
6941
 
; https://cs.stackexchange.com/questions/89245/how-approximate-sine-using-taylor-series
6942
 
; https://stackoverflow.com/questions/42217069/approximating-sinex-with-a-taylor-series-in-c-and-having-a-lot-of-problems
6943
 
;---------------------------------------------------------------------------------------------------------
6944
 
 
6945
 
if defined MATH_SIN or defined MATH_TAN or defined MATH_COS
6946
 
 
6947
 
sinSingle:
6948
 
; taylor: x - x^3/6 + x^5/120 - x^7/5040
6949
 
;         x(1 - x^2(1/6 - x^2(1/120 - x^2/5040)) )
6950
 
; reduction:
6951
 
;         var_b = round( x / (2*PI), 0 )
6952
 
;         var_c = x - var_b*2*PI
6953
 
;         temp1 = if( var_c >= 0, var_c, var_c + 2*PI )
6954
 
;         temp2 = if( temp1 > PI, temp1 - PI, temp1 )
6955
 
;         var_a = if( temp2 > PI/2, PI - temp2, temp2 ) * if( temp1 > PI, -1, 1 )
6956
 
 
6957
 
  call pushpop
6958
 
  ld de, const_0
6959
 
  call cmpSingle
6960
 
  jr nz, sinSingle.1
6961
 
 
6962
 
  call copySingle      ; return 0
6963
 
  ret
6964
 
 
6965
 
sinSingle.1:
6966
 
  call trigRangeReductionSinCos
6967
 
  push bc
6968
 
    ld hl, var_a
6969
 
    ld de, var_a
6970
 
    ld bc, var_b
6971
 
    call mulSingle    ; var_b = var_a * var_a
6972
 
    ld hl, var_b
6973
 
    ld de, sin_a3
6974
 
    ld bc, temp
6975
 
    call mulSingle    ; temp = x^2/5040
6976
 
    ld hl, sin_a2
6977
 
    ld de, temp
6978
 
    ld bc, temp1
6979
 
    call subSingle    ; temp1 = 1/120 - temp
6980
 
    ld hl, var_b
6981
 
    ld de, temp1
6982
 
    ld bc, temp
6983
 
    call mulSingle    ; temp = x^2 * temp1
6984
 
    ld hl, sin_a1
6985
 
    ld de, temp
6986
 
    ld bc, temp1
6987
 
    call subSingle    ; temp1 = 1/6 - temp
6988
 
    ld hl, var_b
6989
 
    ld de, temp1
6990
 
    ld bc, temp
6991
 
    call mulSingle    ; temp = x^2 * temp1
6992
 
    ld hl, const_1
6993
 
    ld de, temp
6994
 
    ld bc, temp1
6995
 
    call subSingle    ; temp1 = 1 - temp
6996
 
    ld hl, var_a
6997
 
    ld de, temp1
6998
 
  pop bc
6999
 
  call mulSingle      ; return x * temp1
7000
 
  ret
7001
 
 
7002
 
trigRangeReductionSinCos:
7003
 
  call pushpop
7004
 
  push hl
7005
 
; var_b = round( x / (2*PI), 0 )
7006
 
    ld de, const_2pi
7007
 
    ld bc, var_c
7008
 
    call divSingle
7009
 
    ld hl, var_c
7010
 
        ld de, 0
7011
 
        ld bc, var_b
7012
 
        call roundSingle
7013
 
; var_c = x - var_b*2*PI
7014
 
    ld hl, var_b
7015
 
    ld de, const_2pi
7016
 
    ld bc, temp
7017
 
    call mulSingle     ; temp = var_b*2*PI
7018
 
  pop hl
7019
 
  ld de, temp
7020
 
  ld bc, var_c
7021
 
  call subSingle     ; var_c = x - temp
7022
 
; temp1 = if( var_c >= 0, var_c, var_c + 2*PI )
7023
 
  ld hl, var_c
7024
 
  ld de, const_0
7025
 
  call cmpSingle
7026
 
  jr nc, trigRangeReductionSinCos.else.2
7027
 
    ld hl, var_c
7028
 
    ld bc, temp1
7029
 
    call copySingle     ; temp1 = var_c
7030
 
    jr trigRangeReductionSinCos.endif.2
7031
 
trigRangeReductionSinCos.else.2:
7032
 
    ld hl, var_c
7033
 
    ld de, const_2pi
7034
 
    ld bc, temp1
7035
 
    call addSingle     ; temp1 = var_c + 2*PI
7036
 
trigRangeReductionSinCos.endif.2:
7037
 
; temp2 = if( temp1 > PI, temp1 - PI, temp1 )
7038
 
  ld hl, const_pi
7039
 
  ld de, temp1
7040
 
  call cmpSingle
7041
 
  jr c, trigRangeReductionSinCos.else.3
7042
 
  jr z, trigRangeReductionSinCos.else.3
7043
 
    ld hl, temp1
7044
 
    ld de, const_pi
7045
 
    ld bc, temp2
7046
 
    call subSingle     ; temp2
7047
 
    jr trigRangeReductionSinCos.endif.3
7048
 
trigRangeReductionSinCos.else.3:
7049
 
    ld hl, temp1
7050
 
    ld bc, temp2
7051
 
    call copySingle     ; temp2 = temp1
7052
 
trigRangeReductionSinCos.endif.3:
7053
 
; var_a = if( temp2 > PI/2, PI - temp2, temp2 ) * if( temp1 > PI, -1, 1 )
7054
 
  ld hl, const_half_pi
7055
 
  ld de, temp2
7056
 
  call cmpSingle
7057
 
  jr c, trigRangeReductionSinCos.else.4
7058
 
  jr z, trigRangeReductionSinCos.else.4
7059
 
    ld hl, const_pi
7060
 
    ld de, temp2
7061
 
    ld bc, var_a
7062
 
    call subSingle     ; var_a
7063
 
    jr trigRangeReductionSinCos.endif.4
7064
 
trigRangeReductionSinCos.else.4:
7065
 
    ld hl, temp2
7066
 
    ld bc, var_a
7067
 
    call copySingle     ; var_a = temp2
7068
 
trigRangeReductionSinCos.endif.4:
7069
 
; if( temp > PI, -1, 1 )
7070
 
  ld hl, temp1
7071
 
  ld de, const_pi
7072
 
  call cmpSingle
7073
 
  jr nc, trigRangeReductionSinCos.endif.5
7074
 
    ld ix, var_a
7075
 
    ld a, (ix+2)
7076
 
    set 7, a
7077
 
    ld (ix+2), a   ; turn var_a to negative
7078
 
trigRangeReductionSinCos.endif.5:
7079
 
; return var_a
7080
 
  ret
7081
 
 
7082
 
endif
7083
 
 
7084
 
;---------------------------------------------------------------------------------------------------------
7085
 
; cosSingle
7086
 
;---------------------------------------------------------------------------------------------------------
7087
 
 
7088
 
if defined MATH_COS or defined MATH_TAN
7089
 
 
7090
 
cosSingle:
7091
 
; taylor: 1 - x^2/2 + x^4/24 - x^6/720
7092
 
;         1 - x^2(1/2 - x^2(1/24 - x^2/720) )
7093
 
; reduction: same as sin
7094
 
;            cos = cos * sign
7095
 
 
7096
 
  call pushpop
7097
 
  ld de, const_0
7098
 
  call cmpSingle
7099
 
  jr nz, cosSingle.1
7100
 
 
7101
 
  ld hl, const_1
7102
 
  call copySingle      ; return 1
7103
 
  ret
7104
 
 
7105
 
cosSingle.1:
7106
 
  ; 1 - x^2(1/2 - x^2(1/24 - x^2/720) )
7107
 
  call trigRangeReductionSinCos
7108
 
  push bc
7109
 
    ld hl, var_a
7110
 
    ld de, var_a
7111
 
    ld bc, var_b
7112
 
    call mulSingle    ; var_b = var_a * var_a
7113
 
    ld hl, var_b
7114
 
    ld de, cos_a3
7115
 
    ld bc, temp
7116
 
    call mulSingle    ; temp = x^2/720
7117
 
    ld hl, cos_a2
7118
 
    ld de, temp
7119
 
    ld bc, temp1
7120
 
    call subSingle    ; temp1 = 1/24 - temp
7121
 
    ld hl, var_b
7122
 
    ld de, temp1
7123
 
    ld bc, temp
7124
 
    call mulSingle    ; temp = x^2 * temp1
7125
 
    ld hl, cos_a1
7126
 
    ld de, temp
7127
 
    ld bc, temp1
7128
 
    call subSingle    ; temp1 = 1/2 - temp
7129
 
    ld hl, var_b
7130
 
    ld de, temp1
7131
 
    ld bc, temp
7132
 
    call mulSingle    ; temp = x^2 * temp1
7133
 
    ld hl, const_1
7134
 
    ld de, temp
7135
 
    ld bc, temp1
7136
 
    call subSingle    ; temp1 = 1 - temp
7137
 
 
7138
 
    ; temp3 = abs(var_c)
7139
 
    ; temp1 = temp1 * if( temp3 >= PI/2, -1, 1 )       ==> cos sign
7140
 
        ld hl, var_c
7141
 
        ld bc, temp3
7142
 
        call copySingle
7143
 
        ld ix, temp3
7144
 
        ld a, (ix+2)
7145
 
    res 7, a
7146
 
        ld (ix+2), a      ; temp3 = abs(var_c)
7147
 
        ld hl, temp3
7148
 
        ld de, const_half_pi
7149
 
    call cmpSingle    ; if temp3 >= PI/2 then temp1 = -temp1
7150
 
    jr nc, cosSingle.endif.1
7151
 
        ld ix, temp1
7152
 
        ld a, (ix+2)
7153
 
    set 7, a
7154
 
        ld (ix+2), a      ; temp1 = -temp1
7155
 
    cosSingle.endif.1:
7156
 
  pop bc
7157
 
  ld hl, temp1
7158
 
  call copySingle      ; return temp1
7159
 
  ret
7160
 
 
7161
 
endif
7162
 
 
7163
 
;---------------------------------------------------------------------------------------------------------
7164
 
; tanSingle
7165
 
;---------------------------------------------------------------------------------------------------------
7166
 
 
7167
 
if defined MATH_TAN
7168
 
 
7169
 
tanSingle:
7170
 
  call pushpop
7171
 
  push bc
7172
 
  ;HL points to input
7173
 
  ld bc,var_z
7174
 
  ld d,b
7175
 
  ld e,c
7176
 
  call cosSingle
7177
 
  ld bc,var_x
7178
 
  call sinSingle
7179
 
  ld h,b
7180
 
  ld l,c
7181
 
  pop bc
7182
 
  jp divSingle
7183
 
 
7184
 
endif
7185
 
 
7186
 
;---------------------------------------------------------------------------------------------------------
7187
 
; atanSingle
7188
 
;---------------------------------------------------------------------------------------------------------
7189
 
 
7190
 
if defined MATH_ATN
7191
 
 
7192
 
atanSingle:
7193
 
;taylor:    x/(1 + x^2/(3 + (2*x)^2/(5 + (3*x)^2/(7+(4*x)^2/9) ) ) )
7194
 
;           x < -1: atan - PI/2
7195
 
;           x >= 1: PI/2 - atan
7196
 
;reduction: abs(X) > 1 : Y = 1 / X
7197
 
;           abs(X) <= 1: Y = X
7198
 
;           X < 0: Y = -Y
7199
 
 
7200
 
  call pushpop
7201
 
  ld de, const_0
7202
 
  call cmpSingle
7203
 
  jr nz, atanSingle.1
7204
 
 
7205
 
  ld hl, const_0
7206
 
  call copySingle      ; return 0
7207
 
  ret
7208
 
 
7209
 
atanSingle.1:
7210
 
  ;x/(1 + x^2/(3 + (2*x)^2/(5 + (3*x)^2/(7+(4*x)^2/9) ) ) )
7211
 
  call trigRangeReductionAtan
7212
 
  push bc
7213
 
  push hl
7214
 
    ld hl, var_a
7215
 
    ld de, var_a
7216
 
    ld bc, var_b
7217
 
    call mulSingle    ; var_b = var_a * var_a
7218
 
    ld hl, var_b
7219
 
    ld de, const_16
7220
 
    ld bc, temp
7221
 
    call mulSingle    ; temp = (4*x)^2
7222
 
    ld hl, temp
7223
 
    ld de, const_9
7224
 
    ld bc, temp1
7225
 
    call divSingle    ; temp1 = temp/9
7226
 
    ld hl, temp1
7227
 
    ld de, const_7
7228
 
    ld bc, temp
7229
 
    call addSingle    ; temp = 7 + temp1
7230
 
    ld hl, var_b
7231
 
    ld de, const_9
7232
 
    ld bc, temp1
7233
 
    call mulSingle    ; temp1 = var_b * 9
7234
 
    ld hl, temp1
7235
 
    ld de, temp
7236
 
    ld bc, temp2
7237
 
    call divSingle    ; temp2 = temp1 / temp
7238
 
    ld hl, temp2
7239
 
    ld de, const_5
7240
 
    ld bc, temp
7241
 
    call addSingle    ; temp = 5 + temp2
7242
 
    ld hl, var_b
7243
 
    ld de, const_4
7244
 
    ld bc, temp1
7245
 
    call mulSingle    ; temp1 = var_b * 4
7246
 
    ld hl, temp1
7247
 
    ld de, temp
7248
 
    ld bc, temp2
7249
 
    call divSingle    ; temp2 = temp1 / temp
7250
 
    ld hl, temp2
7251
 
    ld de, const_3
7252
 
    ld bc, temp
7253
 
    call addSingle    ; temp = 3 + temp2
7254
 
    ld hl, var_b
7255
 
    ld de, temp
7256
 
    ld bc, temp2
7257
 
    call divSingle    ; temp2 = var_b / temp
7258
 
    ld hl, temp2
7259
 
    ld de, const_1
7260
 
    ld bc, temp
7261
 
    call addSingle    ; temp = 1 + temp2
7262
 
    ld hl, var_a
7263
 
    ld de, temp
7264
 
    ld bc, temp2
7265
 
    call divSingle    ; temp2 = var_a / temp
7266
 
  pop hl
7267
 
; x >= 1: PI/2 - atan
7268
 
  ld de, const_1
7269
 
  call cmpSingle
7270
 
  jr nc, atanSingle.2
7271
 
    ld hl, const_half_pi
7272
 
    ld de, temp2
7273
 
    ld bc, temp
7274
 
    call subSingle
7275
 
    ld hl, temp
7276
 
    jr atanSingle.4
7277
 
atanSingle.2:
7278
 
; x < -1: atan - PI/2
7279
 
  push hl
7280
 
    ld hl, const_0
7281
 
        ld de, const_1
7282
 
        ld bc, temp
7283
 
        call subSingle
7284
 
  pop hl
7285
 
  ld de, temp
7286
 
  call cmpSingle
7287
 
  jr c, atanSingle.3
7288
 
    ld hl, temp2
7289
 
    ld de, const_half_pi
7290
 
    ld bc, temp
7291
 
    call subSingle
7292
 
    ld hl, temp
7293
 
    jr atanSingle.4
7294
 
atanSingle.3:
7295
 
  ld hl, temp2
7296
 
atanSingle.4:
7297
 
  pop bc
7298
 
  call copySingle      ; return temp2
7299
 
  ret
7300
 
 
7301
 
trigRangeReductionAtan:
7302
 
;reduction: abs(X) > 1 : Y = 1 / X
7303
 
;           abs(X) <= 1: Y = X
7304
 
;           X < 0: Y = -Y
7305
 
  call pushpop
7306
 
  push hl
7307
 
    ld bc, temp
7308
 
    call copySingle
7309
 
    ld ix, temp
7310
 
    ld a, (ix+2)
7311
 
    res 7, a
7312
 
    ld (ix+2), a   ; abs(x)
7313
 
    ld hl, temp
7314
 
    ld de, const_1
7315
 
    call cmpSingle
7316
 
    jr nc, trigRangeReductionAtan.1
7317
 
      ld hl, const_1
7318
 
          pop de
7319
 
          push de
7320
 
          ld bc, var_a
7321
 
          call divSingle
7322
 
          jr trigRangeReductionAtan.2
7323
 
trigRangeReductionAtan.1:
7324
 
          pop hl
7325
 
          push hl
7326
 
          ld bc, var_a
7327
 
          call copySingle
7328
 
trigRangeReductionAtan.2:
7329
 
  pop hl
7330
 
  ld de, const_0
7331
 
  call cmpSingle
7332
 
  jr c, trigRangeReductionAtan.3
7333
 
    ld ix, var_a
7334
 
    ld a, (ix+2)
7335
 
    set 7, a
7336
 
    ld (ix+2), a   ; y = -y
7337
 
trigRangeReductionAtan.3:
7338
 
  ret
7339
 
 
7340
 
endif
7341
 
 
7342
 
if defined MATH_SIN or defined MATH_TAN or defined MATH_COS
7343
 
 
7344
 
;---------------------------------------------------------------------------------------------------------
7345
 
; copySingle
7346
 
;---------------------------------------------------------------------------------------------------------
7347
 
 
7348
 
copySingle:
7349
 
    call pushpop
7350
 
        ;push bc
7351
 
        ;pop de
7352
 
        ld d, b
7353
 
        ld e, c
7354
 
        ldi
7355
 
        ldi
7356
 
        ldi
7357
 
        ldi
7358
 
        ret
7359
 
 
7360
 
;---------------------------------------------------------------------------------------------------------
7361
 
; roundSingle
7362
 
;---------------------------------------------------------------------------------------------------------
7363
 
 
7364
 
roundSingle:
7365
 
    call pushpop
7366
 
        call copySingle
7367
 
        ;push bc
7368
 
        ;pop hl
7369
 
        ld h, b
7370
 
        ld l, c
7371
 
        push de
7372
 
          ld a, e
7373
 
          ld de, const_10
7374
 
roundSingle.1:
7375
 
          or 0
7376
 
          jr z, roundSingle.2
7377
 
          ld bc, temp
7378
 
          call mulSingle
7379
 
          ;push hl
7380
 
          ;pop bc
7381
 
          ld b, h
7382
 
          ld c, l
7383
 
          ld hl, temp
7384
 
          call copySingle
7385
 
          ;push bc
7386
 
          ;pop hl
7387
 
          ld h, b
7388
 
          ld l, c
7389
 
          dec a
7390
 
          jr roundSingle.1
7391
 
roundSingle.2:
7392
 
      ld de, const_half_1
7393
 
          ld bc, temp
7394
 
          call addSingle
7395
 
      push hl
7396
 
            ld hl, temp
7397
 
            ld bc, temp1
7398
 
            call single2Int
7399
 
            ld hl, temp1
7400
 
          pop bc
7401
 
          call int2Single
7402
 
          ;push bc
7403
 
          ;pop hl
7404
 
          ld h, b
7405
 
          ld l, c
7406
 
        pop de
7407
 
    ld a, e
7408
 
        ld de, const_10
7409
 
roundSingle.3:
7410
 
        or 0
7411
 
        jr z, roundSingle.4
7412
 
        ld bc, temp
7413
 
        call divSingle
7414
 
        ;push hl
7415
 
        ;pop bc
7416
 
        ld b, h
7417
 
        ld c, l
7418
 
        ld hl, temp
7419
 
        call copySingle
7420
 
        ;push bc
7421
 
        ;pop hl
7422
 
        ld h, b
7423
 
        ld l, c
7424
 
        dec a
7425
 
        jr roundSingle.3
7426
 
roundSingle.4:
7427
 
        ret
7428
 
 
7429
 
endif
7430
 
 
7431
 
if defined MATH_ABSFN
7432
 
 
7433
 
;---------------------------------------------------------------------------------------------------------
7434
 
; absSingle
7435
 
;---------------------------------------------------------------------------------------------------------
7436
 
 
7437
 
absSingle:
7438
 
;;HL points to the float
7439
 
;;BC points to where to output the result
7440
 
    call pushpop
7441
 
    ld d,b
7442
 
    ld e,c
7443
 
    ldi
7444
 
    ldi
7445
 
    ld a,(hl)
7446
 
    and %01111111
7447
 
    ld (de),a
7448
 
    inc hl
7449
 
    inc de
7450
 
    ld a,(hl)
7451
 
    ld (de),a
7452
 
    ret
7453
 
 
7454
 
endif
7455
 
 
7456
 
if defined MATH_SGN
7457
 
 
7458
 
;---------------------------------------------------------------------------------------------------------
7459
 
; sgnSingle
7460
 
;---------------------------------------------------------------------------------------------------------
7461
 
 
7462
 
sgnSingle:
7463
 
;;HL points to the float
7464
 
;;BC points to where to output the result
7465
 
    jp negSingle
7466
 
 
7467
 
endif
7468
 
 
7469
 
if defined powSingle or defined sgnSingle or defined MATH_NEG
7470
 
 
7471
 
;---------------------------------------------------------------------------------------------------------
7472
 
; negSingle
7473
 
;---------------------------------------------------------------------------------------------------------
7474
 
 
7475
 
negSingle:
7476
 
;;HL points to the float
7477
 
;;BC points to where to output the result
7478
 
    call pushpop
7479
 
        push hl
7480
 
        pop ix
7481
 
        ld a, (ix+3)
7482
 
        or 0
7483
 
        jr nz, negSingle.test.sign
7484
 
        ld a, (ix+2)
7485
 
        or 0
7486
 
        jr nz, negSingle.test.sign
7487
 
        ld a, (ix+1)
7488
 
        or 0
7489
 
        jr nz, negSingle.test.sign
7490
 
        ld a, (ix)
7491
 
        or 0
7492
 
        jr nz, negSingle.test.sign
7493
 
    ;push bc
7494
 
    ;pop de
7495
 
        ld d, b
7496
 
        ld e, c
7497
 
    ld hl, const_0
7498
 
    ldi
7499
 
    ldi
7500
 
    ldi
7501
 
    ldi
7502
 
    ret
7503
 
negSingle.test.sign:
7504
 
        ld a, (ix+2)
7505
 
        bit 7, a
7506
 
        jr z, negSingle.positive
7507
 
negSingle.negative:
7508
 
    push bc
7509
 
        pop ix
7510
 
        call negSingle.positive
7511
 
        ld a, (ix+2)
7512
 
        set 7, a
7513
 
        ld (ix+2), a
7514
 
    ret
7515
 
negSingle.positive:
7516
 
    ;push bc
7517
 
    ;pop de
7518
 
        ld d, b
7519
 
        ld e, c
7520
 
    ld hl, const_1
7521
 
    ldi
7522
 
    ldi
7523
 
    ldi
7524
 
    ldi
7525
 
    ret
7526
 
 
7527
 
endif
7528
 
 
7529
 
if defined MATH_DCOMP or defined MATH.POW or defined MATH_EXP or defined MATH_LOG or defined MATH_LN or defined MATH_SIN or defined MATH_TAN or defined MATH_COS or defined MATH_ATN
7530
 
 
7531
 
;---------------------------------------------------------------------------------------------------------
7532
 
; cmpSingle
7533
 
;---------------------------------------------------------------------------------------------------------
7534
 
 
7535
 
cmpSingle:
7536
 
;Input: HL points to float1, DE points to float2
7537
 
;Output:
7538
 
;      float1 >= float2 : nc
7539
 
;      float1 <  float2 : c,nz
7540
 
;      float1 == float2 : z
7541
 
;  There is a margin of error allowed in the lower 2 bits of the mantissa.
7542
 
;
7543
 
;Currently fails when both numbers have magnitude less than about 2^-106
7544
 
  push hl
7545
 
  push de
7546
 
  push bc
7547
 
  ld c, a
7548
 
  push bc
7549
 
    ex de, hl
7550
 
    call _30
7551
 
  pop bc
7552
 
  ld a, c
7553
 
  pop bc
7554
 
  pop de
7555
 
  pop hl
7556
 
  ret
7557
 
_30:
7558
 
  inc de
7559
 
  inc de
7560
 
  inc de
7561
 
  ld a,(de)
7562
 
  inc hl
7563
 
  inc hl
7564
 
  inc hl
7565
 
  cp (hl)
7566
 
  jr nc,_31
7567
 
  ld a,(hl)
7568
 
_31:
7569
 
  dec hl
7570
 
  dec hl
7571
 
  dec hl
7572
 
  dec de
7573
 
  dec de
7574
 
  dec de
7575
 
  push af
7576
 
  ld bc,scrap
7577
 
  call subSingle
7578
 
  ld a,(scrap+3)    ;new power
7579
 
  pop bc            ;B is old power
7580
 
  or a
7581
 
  jr z,cmp_close
7582
 
  sub b
7583
 
  jr nc,cmp_is_sign
7584
 
  dec a
7585
 
  add a,22
7586
 
  jr nc,cmp_close
7587
 
cmp_is_sign:
7588
 
  ld a,(scrap+2)
7589
 
  or 1    ;not equal, so reset z flag
7590
 
  rla     ;if negative, float1<float2, setting c flag as wanted, else nc.
7591
 
  ret
7592
 
cmp_close:
7593
 
  xor a
7594
 
  ret
7595
 
 
7596
 
endif
7597
 
 
7598
 
if defined MATH_RND
7599
 
 
7600
 
;---------------------------------------------------------------------------------------------------------
7601
 
; randSingle
7602
 
;---------------------------------------------------------------------------------------------------------
7603
 
 
7604
 
randSingle:
7605
 
;Stores a pseudo-random number on [0,1)
7606
 
;it won't produce values on (0,2^-23)
7607
 
  call pushpop
7608
 
  push bc
7609
 
  call rand
7610
 
  push hl
7611
 
  call rand
7612
 
  pop de
7613
 
  ex de,hl
7614
 
  ld bc,$207F
7615
 
;DEHL is the mantissa, B is the exponent
7616
 
  ld a,d
7617
 
  or a
7618
 
  jp m,rand_normed
7619
 
_32:
7620
 
  dec c
7621
 
  add hl,hl
7622
 
  rl e
7623
 
  rl d
7624
 
  jp m,rand_normed
7625
 
  djnz _32
7626
 
rand_zero:
7627
 
  ld c,l
7628
 
  ld b,l
7629
 
  jr rand_done
7630
 
rand_normed:
7631
 
;If we needed to shift more than 8 bits, we'll load in more random data
7632
 
  ld a,b
7633
 
  cp 8
7634
 
  jr c,rand_zero
7635
 
  sub 24
7636
 
  jp nc,rand_no_more_rand_data
7637
 
  push bc
7638
 
  push de
7639
 
  call rand
7640
 
  pop de
7641
 
  ld e,h
7642
 
  ld h,l
7643
 
  pop bc
7644
 
rand_no_more_rand_data:
7645
 
  ld b,e
7646
 
  ld e,d
7647
 
  ld d,c
7648
 
  ld c,h
7649
 
  res 7,e
7650
 
rand_done:
7651
 
  pop hl
7652
 
  ;DEBC
7653
 
  ld (hl),b
7654
 
  inc hl
7655
 
  ld (hl),c
7656
 
  inc hl
7657
 
  ld (hl),e
7658
 
  inc hl
7659
 
  ld (hl),d
7660
 
  ret
7661
 
 
7662
 
rand:
7663
 
;;Tested and passes all CAcert tests
7664
 
;;Uses a very simple 32-bit LCG and 32-bit LFSR
7665
 
;;it has a period of 18,446,744,069,414,584,320
7666
 
;;roughly 18.4 quintillion.
7667
 
;;LFSR taps: 0,2,6,7  = 11000101
7668
 
;;323cc
7669
 
;;Thanks to Runer112 for his help on optimizing the LCG and suggesting to try the much simpler LCG. On their own, the two are terrible, but together they are great.
7670
 
;Uses 64 bits of state
7671
 
  ld hl,(seed0)
7672
 
  ld de,(seed0+2)
7673
 
  ld b,h
7674
 
  ld c,l
7675
 
  add hl,hl
7676
 
  rl e
7677
 
  rl d
7678
 
  add hl,hl
7679
 
  rl e
7680
 
  rl d
7681
 
  inc l
7682
 
  add hl,bc
7683
 
  ld (seed0),hl
7684
 
  ld hl,(seed0+2)
7685
 
  adc hl,de
7686
 
  ld (seed0+2),hl
7687
 
  ex de,hl
7688
 
;;lfsr
7689
 
  ld hl,(seed1)
7690
 
  ld bc,(seed1+2)
7691
 
  add hl,hl
7692
 
  rl c
7693
 
  rl b
7694
 
  ld (seed1+2),bc
7695
 
  sbc a,a
7696
 
  and %11000101
7697
 
  xor l
7698
 
  ld l,a
7699
 
  ld (seed1),hl
7700
 
  ex de,hl
7701
 
  add hl,bc
7702
 
  ret
7703
 
 
7704
 
endif
7705
 
 
7706
 
if defined MATH_FOUT
7707
 
 
7708
 
;---------------------------------------------------------------------------------------------------------
7709
 
; single2Str
7710
 
; in  HL = Single address
7711
 
;     BC = String address
7712
 
; out A = String size
7713
 
; http://0x80.pl/notesen/2015-12-29-float-to-string.html
7714
 
; http://0x80.pl/articles/convert-float-to-integer.html
7715
 
;---------------------------------------------------------------------------------------------------------
7716
 
 
7717
 
single2str:
7718
 
  call pushpop
7719
 
  push bc
7720
 
  call _33
7721
 
  pop de
7722
 
  xor a
7723
 
  cp (hl)
7724
 
  ldi
7725
 
  jr nz,$-3
7726
 
 
7727
 
  ret
7728
 
_33:
7729
 
; Move the float to scrap
7730
 
  ld de,scrap
7731
 
  call mov4
7732
 
 
7733
 
; Make the float negative, write a '-' if already negative
7734
 
  ld de,strout_single
7735
 
  ld hl,scrap+2
7736
 
  ld a,(hl)
7737
 
  ;rlca
7738
 
  ;scf
7739
 
  ;rra
7740
 
  bit 7, a
7741
 
  jr z, _34
7742
 
  ld a,'-'      ; write '-' simbol
7743
 
  ld (de),a
7744
 
  inc de
7745
 
  ld a,(hl)
7746
 
_34:
7747
 
  set 7, a
7748
 
  ld (hl),a
7749
 
 
7750
 
; Check if the exponent field is 0 (a special value)
7751
 
  inc hl
7752
 
  ld a,(hl)
7753
 
  or a
7754
 
  jp z,strcase_single
7755
 
 
7756
 
 
7757
 
; We should write '0' next. When rounding 9.999999... for example, not padding with a 0 will return '.' instead of '1.'
7758
 
  ex de,hl
7759
 
  ld (hl),'0'
7760
 
  inc hl
7761
 
 
7762
 
; Save the pointer
7763
 
  push hl
7764
 
 
7765
 
; Now we need to perform signed (A-128)*77 (approximation of exponent*log10(2))
7766
 
  ld de,77
7767
 
  ld h,a
7768
 
  ld l,d
7769
 
  call mul8_preset
7770
 
  ld de,-77*128
7771
 
  add hl,de
7772
 
  ld a,h
7773
 
  ld (pow10exp_single),a    ;The base-10 exponent
7774
 
  ld de,pown10LUT
7775
 
  jr c,_35
7776
 
  neg
7777
 
  ld de,pow10LUT   ;get the table of 10^-(2^k)
7778
 
_35:
7779
 
  ld hl, pow10exp_single
7780
 
  ld bc,scrap
7781
 
  call singletostr_mul
7782
 
  call singletostr_mul
7783
 
  call singletostr_mul
7784
 
  call singletostr_mul
7785
 
  call singletostr_mul
7786
 
  call singletostr_mul
7787
 
;now the number is pretty close to a nice value
7788
 
 
7789
 
; If it is less than 1, multiply by 10
7790
 
  ld a,(scrap+3)
7791
 
  sub 128
7792
 
  jr nc,_36
7793
 
  ld de,const_10
7794
 
  ;ld hl,scrap    ;Since singletostr_mul returns BC = scrap, can do this cheaper
7795
 
  ;ld b,h
7796
 
  ;ld c,l
7797
 
  ld h,b
7798
 
  ld l,c
7799
 
  call mulSingle
7800
 
  ld hl,pow10exp_single
7801
 
  dec (hl)
7802
 
  ld a,(scrap+3)
7803
 
  sub 128
7804
 
_36:
7805
 
 
7806
 
; Convert to a fixed-point number !
7807
 
  inc a
7808
 
  ld b,a
7809
 
  xor a
7810
 
_37:
7811
 
  ld hl,scrap
7812
 
  sla (hl)
7813
 
  inc hl
7814
 
  rl (hl)
7815
 
  inc hl
7816
 
  rl (hl)
7817
 
  rla
7818
 
  djnz _37
7819
 
 
7820
 
;We need to get 7 digits
7821
 
  ld b,6
7822
 
  pop hl    ;Points to the string
7823
 
 
7824
 
;The first digit can be as large as 20, so it'll actually be two digits
7825
 
  cp 10
7826
 
  jr c,_38
7827
 
  dec b
7828
 
;Increment the exponent :)
7829
 
  ld de,(pow10exp_single-1)
7830
 
  inc d
7831
 
  ld (pow10exp_single-1),de
7832
 
;
7833
 
  ld (hl),'0'-1
7834
 
  inc (hl)
7835
 
  sub 10
7836
 
  jr nc,$-3
7837
 
  add a,10
7838
 
  inc hl
7839
 
_38:
7840
 
; Get the remaining digits.
7841
 
_39:
7842
 
  add a,'0'
7843
 
  ld (hl),a
7844
 
  inc hl
7845
 
  push hl
7846
 
  push bc
7847
 
  call singletostrmul10
7848
 
  pop bc
7849
 
  pop hl
7850
 
  djnz _39
7851
 
 
7852
 
;Save the pointer to the end of the string
7853
 
  ld d,h
7854
 
  ld e,l
7855
 
  ;ld (hl), 0
7856
 
 
7857
 
;Now let's round!
7858
 
  cp 5
7859
 
  jr c,rounding_done_single
7860
 
  jr _40a  ;.db $DA ;start of `jp c,*` in order to skip the next instruction
7861
 
_40:
7862
 
  ld (hl),'0'
7863
 
_40a:
7864
 
  dec hl
7865
 
  inc (hl)
7866
 
  ld a,(hl)
7867
 
  cp $3A
7868
 
  jr z,_40
7869
 
rounding_done_single:
7870
 
 
7871
 
 
7872
 
;Strip the leading zero if it exists (rounding may have bumped this to `1`)
7873
 
  ld hl,strout_single
7874
 
  ld a,(hl)
7875
 
  cp '-'
7876
 
  jr nz,_41
7877
 
  inc hl
7878
 
  ld a,(hl)
7879
 
_41:
7880
 
  cp '0'
7881
 
  jr nz,_42
7882
 
  dec de
7883
 
  ex de,hl
7884
 
  ;Now lets move HL-DE bytes at DE+1 to DE
7885
 
  sbc hl,de
7886
 
  ld b,h
7887
 
  ld c,l
7888
 
  ld h,d
7889
 
  ld l,e
7890
 
  inc hl
7891
 
  ldir
7892
 
  cp a
7893
 
_42:
7894
 
 
7895
 
  push de
7896
 
;If z flag is reset, this means that the exponent should be bumped up 1
7897
 
  ld a,(pow10exp_single)
7898
 
  jr z,_43
7899
 
  inc a
7900
 
  ld (pow10exp_single),a
7901
 
_43:
7902
 
 
7903
 
  ;if -4<=A<=6, then need to insert the decimal place somewhere.
7904
 
  add a,4
7905
 
  cp 10
7906
 
  jp c,movdec_single
7907
 
_44:
7908
 
  ;for this, we need to insert the decimal after the first digit
7909
 
  ;Then, we need to append the exponent string
7910
 
  ld hl,strout_single
7911
 
  ld de,strout_single-1
7912
 
  ld a,(hl)
7913
 
  cp '-'    ;negative sign
7914
 
  jr nz,_45
7915
 
  ldi
7916
 
_45:
7917
 
  ldi
7918
 
  ld a,'.'
7919
 
  ld (de),a
7920
 
 
7921
 
;remove any stray zeroes at the end before appending the exponent
7922
 
  pop hl
7923
 
  call strip_zeroes
7924
 
 
7925
 
; Write the exponent
7926
 
  ld (hl),'e'
7927
 
  inc hl
7928
 
  ld a,(pow10exp_single)
7929
 
  or a
7930
 
  jp p,_46
7931
 
  ld (hl),'-'    ;negative sign
7932
 
  inc hl
7933
 
  neg
7934
 
_46:
7935
 
  cp 10
7936
 
  jr c,_47
7937
 
  ld (hl),'0'-1
7938
 
  inc (hl)
7939
 
  sub 10
7940
 
  jr nc,$-3
7941
 
  add a,10
7942
 
  inc hl
7943
 
_47:
7944
 
  add a,'0'
7945
 
  ld (hl),a
7946
 
  inc hl
7947
 
  ld (hl),0
7948
 
 
7949
 
  ld de, strout_single
7950
 
  xor a
7951
 
  sbc hl, de
7952
 
  ld a, l         ; string size
7953
 
 
7954
 
  ld hl,strout_single-1
7955
 
  ret
7956
 
 
7957
 
movdec_single:
7958
 
  ld a,(pow10exp_single)
7959
 
  or a
7960
 
  jp p,posdec_single
7961
 
  ld l,a
7962
 
;need to put zeroes before everything
7963
 
  ld de,strout_single
7964
 
  ld a,(de)
7965
 
  cp '-'    ;negative sign
7966
 
  push af
7967
 
  ld a,'0'
7968
 
  jr z,$+3
7969
 
_48:
7970
 
  dec de
7971
 
  ld (de),a
7972
 
  inc l
7973
 
  jr nz,_48
7974
 
_49:
7975
 
  ex de,hl
7976
 
  ld (hl),'.'
7977
 
  pop af
7978
 
  jr nz,_50
7979
 
  dec hl
7980
 
  ld (hl),a
7981
 
_50:
7982
 
  ex de,hl
7983
 
  pop hl
7984
 
  call strip_zeroes
7985
 
  ld (hl),0
7986
 
  ex de,hl
7987
 
  ret
7988
 
 
7989
 
posdec_single:
7990
 
  ld hl,strout_single
7991
 
  ld de,strout_single-1
7992
 
  ld c,a
7993
 
  ld a,(hl)
7994
 
  ld b,0
7995
 
  cp '-'    ;negative sign
7996
 
  jr nz,_51
7997
 
  inc c
7998
 
_51:
7999
 
  inc c
8000
 
  ldir
8001
 
  ld a,'.'
8002
 
  ld (de),a
8003
 
  pop hl
8004
 
  call strip_zeroes
8005
 
  ld (hl),0
8006
 
  ld hl,strout_single-1
8007
 
  ret
8008
 
 
8009
 
strcase_single:
8010
 
  ld hl,str_Zero
8011
 
  ld a,(scrap+2)
8012
 
  add a,a
8013
 
  and $C0
8014
 
  jr z,_52
8015
 
  ld hl,str_Inf
8016
 
  jp pe,_52
8017
 
  ld hl,str_NaN
8018
 
_52:
8019
 
  call mov4
8020
 
  ld hl,strout_single
8021
 
  ret
8022
 
 
8023
 
singletostrmul10:
8024
 
;multiply the 0.24 fixed point number at scrap by 10
8025
 
;overflow in A register
8026
 
  ld a,(scrap+2)
8027
 
  ld e,a
8028
 
  ld hl,(scrap)
8029
 
  xor a
8030
 
  ld d,e
8031
 
  ld b,h
8032
 
  ld c,l
8033
 
  add hl,hl
8034
 
  rl d
8035
 
  rla
8036
 
  add hl,hl
8037
 
  rl d
8038
 
  rla
8039
 
  add hl,bc
8040
 
  ld b,a
8041
 
  ld a,d
8042
 
  adc a,e
8043
 
  ld d,a
8044
 
  ld a,b
8045
 
  adc a,0
8046
 
  add hl,hl
8047
 
  rl d
8048
 
  rla
8049
 
  ld (scrap+1),de
8050
 
  ld (scrap),hl
8051
 
  ret
8052
 
 
8053
 
strip_zeroes:
8054
 
  ld a,'0'
8055
 
_53:
8056
 
  dec hl
8057
 
  cp (hl)
8058
 
  jr z,_53
8059
 
 
8060
 
;Check that the last  digit isn't a decimal!
8061
 
  ld a,'.'
8062
 
  cp (hl)
8063
 
  ret z
8064
 
  inc hl
8065
 
  ret
8066
 
 
8067
 
singletostr_mul:
8068
 
  rra
8069
 
  call c,_54
8070
 
  ld hl,4
8071
 
  add hl,de
8072
 
  ex de,hl
8073
 
  ret
8074
 
_54:
8075
 
  ld h,b
8076
 
  ld l,c
8077
 
  jp mulSingle
8078
 
mul8:
8079
 
;H*E => HL
8080
 
  ld l,0
8081
 
  ld d,l
8082
 
mul8_preset:
8083
 
  sla h
8084
 
  jr nc,$+3
8085
 
  ld l,e
8086
 
  add hl,hl
8087
 
  jr nc,$+3
8088
 
  add hl,de
8089
 
  add hl,hl
8090
 
  jr nc,$+3
8091
 
  add hl,de
8092
 
  add hl,hl
8093
 
  jr nc,$+3
8094
 
  add hl,de
8095
 
  add hl,hl
8096
 
  jr nc,$+3
8097
 
  add hl,de
8098
 
  add hl,hl
8099
 
  jr nc,$+3
8100
 
  add hl,de
8101
 
  add hl,hl
8102
 
  jr nc,$+3
8103
 
  add hl,de
8104
 
  add hl,hl
8105
 
  ret nc
8106
 
  add hl,de
8107
 
  ret
8108
 
 
8109
 
endif
8110
 
 
8111
 
 
8112
 
if defined MATH_FIN
8113
 
 
8114
 
;---------------------------------------------------------------------------------------------------------
8115
 
; str2Single
8116
 
; https://www.ticalc.org/pub/86/asm/source/routines/atof.asm
8117
 
;---------------------------------------------------------------------------------------------------------
8118
 
 
8119
 
char_NEG: equ  '-'
8120
 
char_ENG: equ  ','
8121
 
char_DEC: equ  '.'
8122
 
ptr_sto: equ scrap+9
8123
 
 
8124
 
;;#Routines/Single Precision
8125
 
;;Inputs:
8126
 
;;  HL points to the string
8127
 
;;  BC points to where the float is output
8128
 
;;Output:
8129
 
;;  scrap+9 is the pointer to the end of the string
8130
 
;;Destroys:
8131
 
;;  11 bytes at scrap ?
8132
 
 
8133
 
str2single:
8134
 
  call pushpop
8135
 
  push bc
8136
 
;Check if there is a negative sign.
8137
 
;   Save for later
8138
 
;   Advance ptr
8139
 
  ld a,(hl)
8140
 
  sub char_NEG
8141
 
  sub 1
8142
 
  push af
8143
 
  jr nc,$+3
8144
 
  inc hl
8145
 
;Skip all leading zeroes
8146
 
  ld a,(hl)
8147
 
  cp '0'
8148
 
  jr z,$-4      ;jumps back to the `inc hl`
8149
 
;Set exponent to 0
8150
 
  ld b,0
8151
 
;Check if the next char is char_DEC
8152
 
  sub char_DEC
8153
 
  or a      ;to reset the carry flag
8154
 
  jr nz,_55
8155
 
  jr _54a   ;.db $FE   ;start of cp *
8156
 
;Get rid of zeroes
8157
 
  dec b
8158
 
_54a:
8159
 
  inc hl
8160
 
  ld a,(hl)
8161
 
  cp '0'
8162
 
  jr z,$-5      ;jumps back to the `dec b`
8163
 
  scf
8164
 
_55:
8165
 
;Now we read in the next 8 digits
8166
 
  ld de,scrap+3
8167
 
  call ascii_to_uint8
8168
 
  call ascii_to_uint8
8169
 
  call ascii_to_uint8
8170
 
  call ascii_to_uint8
8171
 
;Now `scrap` holds the 4-digit base-100 number.
8172
 
;b is the exponent
8173
 
;if carry flag is set, just need to get rid of remaining digits
8174
 
;Otherwise, need to get rid of remaining digits, while incrementing the exponent
8175
 
  sbc a,a
8176
 
  inc a
8177
 
  ld c,a
8178
 
_56:
8179
 
  ld a,(hl)
8180
 
  cp 30h
8181
 
  jr nz,_57
8182
 
  inc hl
8183
 
  ld a,b
8184
 
  add a,c
8185
 
  jp z,strToSingle_inf
8186
 
  ld b,a
8187
 
  jr _56
8188
 
;Now check for engineering `E` to modify the exponent
8189
 
_57:
8190
 
  cp char_NEG
8191
 
  call z,str_eng_exp
8192
 
;Gotta multiply the number at (scrap) by 2^24
8193
 
  ld (ptr_sto),hl
8194
 
  ld d,100
8195
 
  call scrap_times_256
8196
 
  ld a,c
8197
 
  ld (scrap+6),a
8198
 
  call scrap_times_256
8199
 
  ld a,c
8200
 
  ld (scrap+5),a
8201
 
  call scrap_times_256
8202
 
  ld a,c
8203
 
  ld (scrap+4),a
8204
 
  call scrap_times_256
8205
 
  ld a,c
8206
 
  ld (scrap+3),a
8207
 
;Now scrap+3 is a 4-byte mantissa that needs to be normalized
8208
 
;
8209
 
  ld hl,(scrap+3)
8210
 
  ld a,h
8211
 
  or l
8212
 
  ld hl,(scrap+5)
8213
 
  or l
8214
 
  or h
8215
 
  jp z,strToSingle_zero-1
8216
 
  ld c,$7F
8217
 
  ld a,h
8218
 
  or a
8219
 
  jp m,strToSingle_normed
8220
 
  ;Will need to iterate at most three times
8221
 
_58:
8222
 
  dec c
8223
 
  ld hl,scrap+3
8224
 
  sla (hl)
8225
 
  inc hl
8226
 
  rl (hl)
8227
 
  inc hl
8228
 
  rl (hl)
8229
 
  inc hl
8230
 
  adc a,a
8231
 
  jp p,_58
8232
 
strToSingle_normed:
8233
 
;Move the number to scrap
8234
 
  ld hl,(scrap+4)
8235
 
  ld (scrap),hl
8236
 
  ld l,a
8237
 
  ld h,c
8238
 
  sla l
8239
 
  pop af
8240
 
  rr l
8241
 
  ld (scrap+2),hl
8242
 
;now (scrap) is our number, need to multiply by power of 10!
8243
 
;Power of 10 is stored in B, need to put in A first
8244
 
  xor a
8245
 
  sub b
8246
 
  ld de,pown10LUT
8247
 
  jp p,_59
8248
 
  ld a,b
8249
 
  ld de,pow10LUT
8250
 
  cp 40
8251
 
  jp nc,strToSingle_inf+1
8252
 
_59:
8253
 
  cp 40
8254
 
  jp nc,strToSingle_zero
8255
 
  ld hl,scrap
8256
 
  ld b,h
8257
 
  ld c,l
8258
 
  call _60
8259
 
  call _60
8260
 
  call _60
8261
 
  call _60
8262
 
  call _60
8263
 
  call _60
8264
 
  pop de
8265
 
  jp mov4
8266
 
_60:
8267
 
  rra
8268
 
  call c,mulSingle
8269
 
  inc de
8270
 
  inc de
8271
 
  inc de
8272
 
  inc de
8273
 
  ret
8274
 
str_eng_exp:
8275
 
  ld de,0
8276
 
  inc hl
8277
 
  ld a,(hl)
8278
 
  cp char_NEG    ;negative exponent?
8279
 
  push af
8280
 
  jr nz,$+3
8281
 
  inc hl
8282
 
_61:
8283
 
  ld a,(hl)
8284
 
  sub 3Ah
8285
 
  add a,10
8286
 
  jr nc,_62
8287
 
  inc hl
8288
 
  push hl
8289
 
  ld h,d
8290
 
  ld l,e
8291
 
  add hl,hl
8292
 
  add hl,hl
8293
 
  add hl,de
8294
 
  add hl,hl
8295
 
  add a,l
8296
 
  ld l,a
8297
 
  ex de,hl
8298
 
  pop hl
8299
 
  jp c,eng_overflow
8300
 
  inc d
8301
 
  dec d
8302
 
  jp z,_61
8303
 
  jp nz,eng_overflow
8304
 
_62:
8305
 
  ld a,e
8306
 
  cp 40
8307
 
  jr nc,eng_overflow
8308
 
  pop af
8309
 
  ld a,b
8310
 
  jr nz,_63
8311
 
  sub e
8312
 
  ld b,a
8313
 
  ret
8314
 
_63:
8315
 
  add a,e
8316
 
  ld b,a
8317
 
  ret
8318
 
scrap_times_256:
8319
 
  ld e,8
8320
 
_64:
8321
 
  or a
8322
 
  ld hl,scrap
8323
 
  call _65
8324
 
  call _65
8325
 
  rl c
8326
 
  dec e
8327
 
  jr nz,_64
8328
 
  ret
8329
 
_65:
8330
 
  call scrap_times_sub
8331
 
scrap_times_sub:
8332
 
  ld a,(hl)
8333
 
  rla
8334
 
  cp d
8335
 
  jr c,$+3
8336
 
  sub d
8337
 
  ld (hl),a
8338
 
  inc hl
8339
 
  ccf
8340
 
  ret
8341
 
eng_overflow:
8342
 
  pop af
8343
 
  jr nz,strToSingle_inf
8344
 
  pop af
8345
 
strToSingle_zero:
8346
 
  ld hl,const_0
8347
 
  pop de
8348
 
  jp mov4
8349
 
strToSingle_inf:
8350
 
;return inf
8351
 
  pop af
8352
 
  ld hl,const_inf
8353
 
  jr nc,_66
8354
 
  ld hl,const_NegInf
8355
 
_66:
8356
 
  pop de
8357
 
  jp mov4
8358
 
 
8359
 
endif
8360
 
 
8361
 
if defined roundSingle or defined MATH_FRCSGL
8362
 
 
8363
 
;---------------------------------------------------------------------------------------------------------
8364
 
; int2Single
8365
 
; http://wikiti.brandonw.net/index.php?title=Z80_Routines:Math:Division#24.2F8_division
8366
 
;---------------------------------------------------------------------------------------------------------
8367
 
 
8368
 
int2Single:
8369
 
    call pushpop
8370
 
        push bc
8371
 
            push hl
8372
 
                pop ix
8373
 
            ld l, (ix)            ; convert integer parameter to single float
8374
 
                ld h, (ix+1)
8375
 
                ld bc, 0x1000         ; bynary digits count + sign
8376
 
 
8377
 
int2Single.test.zero:
8378
 
        xor a
8379
 
                or h                  ; test if hl is not zero
8380
 
                jr nz, int2Single.test.negative
8381
 
                or l
8382
 
                jr nz, int2Single.test.negative
8383
 
                ld hl, 0
8384
 
                ld de, 0
8385
 
                jp int2Single.save
8386
 
 
8387
 
int2Single.test.negative:
8388
 
        bit 7, h              ; test if hl is negative
8389
 
                jr z, int2Single.normalize
8390
 
                ld c, 0x80            ; sign negative
8391
 
                ld a, h               ;\
8392
 
                cpl                   ; |
8393
 
                ld h, a               ; | abs(hl)
8394
 
                ld a, l               ; |
8395
 
                cpl                   ; |
8396
 
                ld l, a               ;/
8397
 
                inc hl
8398
 
 
8399
 
int2Single.normalize:
8400
 
        dec b
8401
 
        bit 7, h
8402
 
                jr nz, int2Single.mount
8403
 
                sla l
8404
 
                rl h
8405
 
                jr int2Single.normalize
8406
 
 
8407
 
int2Single.mount:
8408
 
                res 7, h              ; turn off upper bit
8409
 
 
8410
 
        ld a, c               ; restore sign
8411
 
        or h                  ; put sign...
8412
 
        ld h, a               ; ...into upper mantissa
8413
 
 
8414
 
                ld e, h               ; sign+mantissa
8415
 
                ld h, l               ; high mantissa
8416
 
                ld l, 0               ; low mantissa
8417
 
 
8418
 
        ld a, b               ; binary digits count
8419
 
        or 0x80               ; exponent bias
8420
 
        ld d, a               ; exponent
8421
 
 
8422
 
int2Single.save:
8423
 
    pop ix
8424
 
        ld (ix),   l          ; low mantissa
8425
 
        ld (ix+1), h          ; high mantissa
8426
 
        ld (ix+2), e          ; sign + mantissa
8427
 
        ld (ix+3), d          ; expoent
8428
 
        ld (ix+4), 0
8429
 
        ld (ix+5), 0
8430
 
        ld (ix+6), 0
8431
 
        ld (ix+7), 0
8432
 
        ret
8433
 
 
8434
 
endif
8435
 
 
8436
 
if defined roundSingle or defined MATH_FRCINT
8437
 
 
8438
 
;---------------------------------------------------------------------------------------------------------
8439
 
; single2Int
8440
 
; http://0x80.pl/articles/convert-float-to-integer.html
8441
 
;---------------------------------------------------------------------------------------------------------
8442
 
single2Int:
8443
 
;Input:
8444
 
; HL points to the single-precision float
8445
 
;Output:
8446
 
; HL is the 16-bit signed integer part of the float
8447
 
; BC points to 16-bit signed integer
8448
 
  call pushpop
8449
 
  push bc
8450
 
    ld e,(hl)
8451
 
    inc hl
8452
 
    ld d,(hl)
8453
 
    inc hl
8454
 
    ld a,(hl)
8455
 
    add a,a
8456
 
    push af
8457
 
    scf
8458
 
    rra
8459
 
    ld c,a
8460
 
    inc hl
8461
 
    ld a,(hl)
8462
 
    ld hl,0
8463
 
    sub 80h
8464
 
    jr c,no_shift_single_to_int16
8465
 
    cp 39
8466
 
    jr nc,no_shift_single_to_int16
8467
 
    sub 8
8468
 
    jr c,_67
8469
 
    ld l,c
8470
 
    ld c,d
8471
 
    ld d,e
8472
 
    ld e,h
8473
 
    sub 8
8474
 
    jr c,_67
8475
 
    ld h,l
8476
 
    ld l,c
8477
 
    ld c,d
8478
 
    ld d,e
8479
 
    sub 8
8480
 
    jr c,_67
8481
 
    ld h,l
8482
 
    ld l,c
8483
 
    ld c,d
8484
 
    sub 8
8485
 
    jr c,_67
8486
 
    ld h,l
8487
 
    ld l,c
8488
 
    jr _67a ;.db $11 ;start of ld de,*
8489
 
_67:
8490
 
    add a,9
8491
 
_67a:
8492
 
    ld b,a
8493
 
    ld a,e
8494
 
_68:
8495
 
    add a,a
8496
 
    rl d
8497
 
    rl c
8498
 
    adc hl,hl
8499
 
    djnz _68
8500
 
no_shift_single_to_int16:
8501
 
    pop af
8502
 
    jr nc,_69
8503
 
    ;need to negate
8504
 
    xor a
8505
 
    sub e
8506
 
    ld e,0
8507
 
    ld a,e
8508
 
    sbc a,d
8509
 
    ld a,e
8510
 
    sbc a,c
8511
 
    ld d,e
8512
 
    ex de,hl
8513
 
    sbc hl,de
8514
 
_69:
8515
 
  pop ix
8516
 
  ld (ix), l
8517
 
  ld (ix+1), h
8518
 
  ret
8519
 
 
8520
 
endif
8521
 
 
8522
 
;---------------------------------------------------------------------------------------------------------
8523
 
; Auxiliary routines
8524
 
;---------------------------------------------------------------------------------------------------------
8525
 
 
8526
 
str_Zero: db "0",0
8527
 
str_Inf:  db "inf",0
8528
 
str_NaN:  db "NaN",0
8529
 
 
8530
 
start_const:
8531
 
const_pi:      db $DB,$0F,$49,$81
8532
 
const_e:       db $54,$f8,$2d,$81
8533
 
const_lg_e:    db $3b,$AA,$38,$80
8534
 
const_ln_2:    db $18,$72,$31,$7f
8535
 
const_log2:    db $9b,$20,$1a,$7e
8536
 
const_lg10:    db $78,$9a,$54,$81
8537
 
const_0:       db $00,$00,$00,$00
8538
 
const_1:       db $00,$00,$00,$80
8539
 
const_2:       dw 0, 33024
8540
 
const_3:       dw 0, 33088
8541
 
const_4:       dw 0, 33280
8542
 
const_5:       dw 0, 33312
8543
 
const_7:       dw 0, 33376
8544
 
const_9:       dw 0, 33552
8545
 
const_16:      dw 0, 33792
8546
 
const_100:     db $00,$00,$48,$86
8547
 
const_100_inv: dw 55050, 31011
8548
 
const_precision: db $77,$CC,$2B,$65  ;10^-8
8549
 
const_half_1:  dw 0, 32512
8550
 
const_inf:     db $00,$00,$40,$00
8551
 
const_NegInf:  db $00,$00,$C0,$00
8552
 
const_NaN:     db $00,$00,$20,$00
8553
 
const_log10_e: db $D9,$5B,$5E,$7E
8554
 
const_2pi:     db $DB,$0F,$49,$82
8555
 
const_2pi_inv: db $83,$F9,$22,$7D
8556
 
const_half_pi: dw 4059, 32841
8557
 
const_p25:     db $00,$00,$00,$7E
8558
 
const_p5:      db $00,$00,$00,$7F
8559
 
;     db $,$,$,$
8560
 
end_const:
8561
 
sin_a1: dw 43691, 32042
8562
 
sin_a2: dw 34952, 30984
8563
 
sin_a3: dw 3329, 29520
8564
 
cos_a1: equ const_half_1
8565
 
cos_a2: dw 43691, 31530
8566
 
cos_a3: dw 2914, 30262
8567
 
exp_a1: db $15,$72,$31,$7F  ;.693146989552
8568
 
exp_a2: db $CE,$FE,$75,$7D  ;.2402298085906
8569
 
exp_a3: db $7B,$42,$63,$7B  ;.0554833215071
8570
 
exp_a4: db $FD,$94,$1E,$79  ;.00967907584392
8571
 
exp_a5: db $5E,$01,$23,$76  ;.001243632065103
8572
 
exp_a6: db $5F,$B7,$63,$73  ;.0002171671843714
8573
 
const_1p40625: db $00,$00,$34,$80  ;1.40625
8574
 
 
8575
 
if defined MATH_CONSTSINGLE
8576
 
 
8577
 
iconstSingle:
8578
 
    ex (sp),hl
8579
 
    ld a,(hl)
8580
 
    inc hl
8581
 
    ex (sp),hl
8582
 
constSingle:
8583
 
;A is the constant ID#
8584
 
;returns nc if failed, c otherwise
8585
 
;HL points to the constant
8586
 
    cp (end_const-start_const)>>2
8587
 
    ret nc
8588
 
    ld hl,start_const
8589
 
    add a,a
8590
 
    add a,a
8591
 
    add a,l
8592
 
    ld l,a
8593
 
;#if ((end_const-4)>>8)!=(start_const>>8)
8594
 
;    ccf
8595
 
;    ret c
8596
 
;    inc h
8597
 
;#endif
8598
 
    scf
8599
 
    ret
8600
 
 
8601
 
endif
8602
 
 
8603
 
;;LUTs used
8604
 
lut:
8605
 
pown10LUT:
8606
 
db $CD,$CC,$4C,$7C  ;.1
8607
 
db $0A,$D7,$23,$79  ;.01
8608
 
db $17,$B7,$51,$72  ;.0001
8609
 
db $77,$CC,$2B,$65  ;10^-8
8610
 
db $95,$95,$66,$4A  ;10^-16
8611
 
db $1F,$B1,$4F,$15  ;10^-32
8612
 
pow10LUT:
8613
 
const_10:
8614
 
db $00,$00,$20,$83 ;10
8615
 
db $00,$00,$48,$86 ;100
8616
 
db $00,$40,$1C,$8D ;10000
8617
 
db $20,$BC,$3E,$9A ;10^8
8618
 
db $CA,$1B,$0E,$B5 ;10^16
8619
 
db $AE,$C5,$1D,$EA ;10^32
8620
 
 
8621
 
C_Times_BDE:
8622
 
;;C*BDE => CAHL
8623
 
;C = 0     157
8624
 
;C = 1     141
8625
 
;141+
8626
 
;C>=128    135+6{0,33+{0,1}}+{0,20+{0,8}}
8627
 
;C>=64     115+5{0,33+{0,1}}+{0,20+{0,8}}
8628
 
;C>=32     95+4{0,33+{0,1}}+{0,20+{0,8}}
8629
 
;C>=16     75+3{0,33+{0,1}}+{0,20+{0,8}}
8630
 
;C>=8      55+2{0,33+{0,1}}+{0,20+{0,8}}
8631
 
;C>=4      35+{0,33+{0,1}}+{0,20+{0,8}}
8632
 
;C>=2      15+{0,20+{0,8}}
8633
 
;min: 141cc
8634
 
;max: 508cc
8635
 
;avg: 349.21279907227cc
8636
 
 
8637
 
  ld a,b
8638
 
  ld h,d
8639
 
  ld l,e
8640
 
  sla c
8641
 
  jr c,mul8_24_1
8642
 
  sla c
8643
 
  jr c,mul8_24_2
8644
 
  sla c
8645
 
  jr c,mul8_24_3
8646
 
  sla c
8647
 
  jr c,mul8_24_4
8648
 
  sla c
8649
 
  jr c,mul8_24_5
8650
 
  sla c
8651
 
  jr c,mul8_24_6
8652
 
  sla c
8653
 
  jr c,mul8_24_7
8654
 
  sla c
8655
 
  ret c
8656
 
  ld a,c
8657
 
  ld h,c
8658
 
  ld l,c
8659
 
  ret
8660
 
mul8_24_1:
8661
 
    add hl,hl
8662
 
    rla
8663
 
    rl c
8664
 
    jr nc,$+7
8665
 
    add hl,de
8666
 
    adc a,b
8667
 
    jr nc,$+3
8668
 
    inc c
8669
 
mul8_24_2:
8670
 
    add hl,hl
8671
 
    rla
8672
 
    rl c
8673
 
    jr nc,$+7
8674
 
    add hl,de
8675
 
    adc a,b
8676
 
    jr nc,$+3
8677
 
    inc c
8678
 
mul8_24_3:
8679
 
    add hl,hl
8680
 
    rla
8681
 
    rl c
8682
 
    jr nc,$+7
8683
 
    add hl,de
8684
 
    adc a,b
8685
 
    jr nc,$+3
8686
 
    inc c
8687
 
mul8_24_4:
8688
 
    add hl,hl
8689
 
    rla
8690
 
    rl c
8691
 
    jr nc,$+7
8692
 
    add hl,de
8693
 
    adc a,b
8694
 
    jr nc,$+3
8695
 
    inc c
8696
 
mul8_24_5:
8697
 
    add hl,hl
8698
 
    rla
8699
 
    rl c
8700
 
    jr nc,$+7
8701
 
    add hl,de
8702
 
    adc a,b
8703
 
    jr nc,$+3
8704
 
    inc c
8705
 
mul8_24_6:
8706
 
    add hl,hl
8707
 
    rla
8708
 
    rl c
8709
 
    jr nc,$+7
8710
 
    add hl,de
8711
 
    adc a,b
8712
 
    jr nc,$+3
8713
 
    inc c
8714
 
mul8_24_7:
8715
 
    add hl,hl
8716
 
    rla
8717
 
    rl c
8718
 
    ret nc
8719
 
    add hl,de
8720
 
    adc a,b
8721
 
    ret nc
8722
 
    inc c
8723
 
    ret
8724
 
 
8725
 
pushpop:
8726
 
;26 bytes, adds 118cc to the traditional routine
8727
 
  ex (sp),hl
8728
 
  push de
8729
 
  push bc
8730
 
  push af
8731
 
  push hl
8732
 
  ld hl,pushpopret
8733
 
  ex (sp),hl
8734
 
  push hl
8735
 
  push af
8736
 
  ld hl,12
8737
 
  add hl,sp
8738
 
  ld a,(hl)
8739
 
  inc hl
8740
 
  ld h,(hl)
8741
 
  ld l,a
8742
 
  pop af
8743
 
  ret
8744
 
pushpopret:
8745
 
  pop af
8746
 
  pop bc
8747
 
  pop de
8748
 
  pop hl
8749
 
  ret
8750
 
 
8751
 
mov4:
8752
 
  ldi
8753
 
  ldi
8754
 
  ldi
8755
 
  ldi
8756
 
  ret
8757
 
 
8758
 
if defined MATH_FIN
8759
 
 
8760
 
ascii_to_uint8:
8761
 
;c flag means don't increment the exponent
8762
 
  ld c,0
8763
 
  ld a,(hl)
8764
 
  jr c,ascii_to_uint8_noexp
8765
 
  cp char_DEC
8766
 
  jr z,ascii_to_uint8_noexp-2
8767
 
_70:
8768
 
  sub 3Ah
8769
 
  add a,10
8770
 
  jr nc,ascii_to_uint8_noexp_end
8771
 
  inc b
8772
 
  ld c,a
8773
 
  add a,a
8774
 
  add a,a
8775
 
  add a,c
8776
 
  add a,a
8777
 
  ld c,a
8778
 
  inc hl
8779
 
_71:
8780
 
  ld a,(hl)
8781
 
  cp char_DEC
8782
 
  jr z,ascii_to_uint8_noexp_2nd
8783
 
_72:
8784
 
  sub 3Ah
8785
 
  add a,10
8786
 
  jr nc,ascii_to_uint8_noexp_end
8787
 
  inc b
8788
 
  add a,c
8789
 
  inc hl
8790
 
  ld (de),a
8791
 
  dec de
8792
 
  or a
8793
 
  ret
8794
 
 
8795
 
  inc hl
8796
 
  ld a,(hl)
8797
 
ascii_to_uint8_noexp:
8798
 
  sub 3Ah
8799
 
  add a,10
8800
 
  jr nc,ascii_to_uint8_noexp_end
8801
 
  ld c,a
8802
 
  add a,a
8803
 
  add a,a
8804
 
  add a,c
8805
 
  add a,a
8806
 
  ld c,a
8807
 
ascii_to_uint8_noexp_2nd:
8808
 
  inc hl
8809
 
  ld a,(hl)
8810
 
  sub 3Ah
8811
 
  add a,10
8812
 
  jr nc,ascii_to_uint8_noexp_end
8813
 
  add a,c
8814
 
  inc hl
8815
 
  jr ascii_2  ;.db $FE   ;start of `cp **`, saves 1cc
8816
 
ascii_to_uint8_noexp_end:
8817
 
  ld a,c
8818
 
ascii_2:
8819
 
  ld (de),a
8820
 
  dec de
8821
 
  scf
8822
 
  ret
8823
 
 
8824
 
endif
8825
 
 
8826
 
if defined MATH_RSUBSINGLE
8827
 
 
8828
 
rsubSingle:
8829
 
;;-x+y
8830
 
    push af
8831
 
    push hl
8832
 
    push de
8833
 
    push bc
8834
 
    push de
8835
 
    ld de,addend2
8836
 
    ldi
8837
 
    ldi
8838
 
    ld a,(hl)
8839
 
    xor 80h
8840
 
    ld (de),a
8841
 
    inc de
8842
 
    inc hl
8843
 
    ld a,(hl)
8844
 
    ld (de),a
8845
 
    pop de
8846
 
    ld hl,addend2
8847
 
    jp addInject    ;jumps in to the addSingle routine
8848
 
 
8849
 
endif
8850
 
 
8851
 
if defined MATH_MOD1SINGLE
8852
 
 
8853
 
;This routine performs `x mod 1`, returning a non-negative value.
8854
 
;+inf -> NaN
8855
 
;-inf -> NaN
8856
 
;NaN  -> NaN
8857
 
mod1Single:
8858
 
  call pushpop
8859
 
  push bc
8860
 
  ld e,(hl)
8861
 
  inc hl
8862
 
  ld d,(hl)
8863
 
  inc hl
8864
 
  ld c,(hl)
8865
 
  ld a,c
8866
 
  xor 80h
8867
 
  push af
8868
 
  jp p,mod1Single.1
8869
 
  ld c,a
8870
 
mod1Single.1:
8871
 
 
8872
 
  inc hl
8873
 
  ld a,(hl)
8874
 
  ld b,a
8875
 
  or a
8876
 
  jr z,mod1Single_special
8877
 
  sub $80
8878
 
  jr c,mod1_end
8879
 
  inc a
8880
 
  ld b,a
8881
 
  ld a,c
8882
 
  ex de,hl
8883
 
mod1Single.2:
8884
 
  add hl,hl
8885
 
  rla
8886
 
  djnz mod1Single.2
8887
 
  ld c,a
8888
 
 
8889
 
;If it is zero, need to set exponent to zero and return
8890
 
  or h
8891
 
  or l
8892
 
  ex de,hl
8893
 
  jr z,mod1_end
8894
 
 
8895
 
;Need to normalize
8896
 
  ld b,$7F
8897
 
  ld a,c
8898
 
  or a
8899
 
  jp m,mod1_end
8900
 
  ex de,hl
8901
 
mod1Single.3:
8902
 
  dec b
8903
 
  add hl,hl
8904
 
  adc a,a
8905
 
  jp p,mod1Single.3
8906
 
  ld c,a
8907
 
  ex de,hl
8908
 
mod1_end:
8909
 
  pop af
8910
 
  pop hl
8911
 
  jp m,mod1Single.4
8912
 
  ;make sure it isn't zero else we need to add 1
8913
 
  ld a,b
8914
 
  or a
8915
 
  jr z,mod1Single.4
8916
 
  ld (scrap),de
8917
 
  ld (scrap+2),bc
8918
 
  ld b,h
8919
 
  ld c,l
8920
 
  ld hl,scrap
8921
 
  ld de,const_1
8922
 
  jp addSingle
8923
 
mod1Single_special:
8924
 
;If INF, need to return NaN instead
8925
 
;For 0 and NaN, just return itself :)
8926
 
  pop af
8927
 
  pop hl
8928
 
  ld a,c
8929
 
  add a,a
8930
 
  jp p,mod1Single.4
8931
 
  ld c,$40
8932
 
mod1Single.4:
8933
 
  res 7,c
8934
 
  ld (hl),e
8935
 
  inc hl
8936
 
  ld (hl),d
8937
 
  inc hl
8938
 
  ld (hl),c
8939
 
  inc hl
8940
 
  ld (hl),b
8941
 
  ret
8942
 
 
8943
 
endif
8944
 
 
8945
 
if defined MATH_FOUT
8946
 
 
8947
 
; --------------------------------------------------------------
8948
 
; Converts a signed integer value to a zero-terminated ASCII
8949
 
; string representative of that value (using radix 10).
8950
 
; References:
8951
 
; Brandon Wilson WikiTI
8952
 
; http://wikiti.brandonw.net/index.php?title=Z80_Routines:Other:DispA#Decimal_Signed_Version
8953
 
; --------------------------------------------------------------
8954
 
; INPUTS:
8955
 
;     HL     Value to convert (two's complement integer).
8956
 
;     DE     Base address of string destination. (pointer).
8957
 
; --------------------------------------------------------------
8958
 
; OUTPUTS:
8959
 
;     A      Size of string
8960
 
; --------------------------------------------------------------
8961
 
; REGISTERS/MEMORY DESTROYED
8962
 
; AF HL
8963
 
; --------------------------------------------------------------
8964
 
 
8965
 
IntToStr:
8966
 
   push    de
8967
 
   push    bc
8968
 
 
8969
 
; Detect sign of HL.
8970
 
    bit    7, h
8971
 
    jr     z, _DoConvert
8972
 
 
8973
 
; HL is negative. Output '-' to string and negate HL.
8974
 
    ld     a, '-'
8975
 
    ld     (de), a
8976
 
    inc    de
8977
 
 
8978
 
; Negate HL (using two's complement)
8979
 
    xor    a
8980
 
    sub    l
8981
 
    ld     l, a
8982
 
    ld     a, 0     ; Note that XOR A or SUB A would disturb CF
8983
 
    sbc    a, h
8984
 
    ld     h, a
8985
 
 
8986
 
; Convert HL to digit characters
8987
 
_DoConvert:
8988
 
    ld     b, 0     ; B will count character length of number
8989
 
_DoConvert.1:
8990
 
    ld     c, 10
8991
 
    call div_hl_c; HL = HL / A, A = remainder
8992
 
    push   af
8993
 
    inc    b
8994
 
    ld     a, h
8995
 
    or     l
8996
 
    jr     nz, _DoConvert.1
8997
 
 
8998
 
; Retrieve digits from stack
8999
 
_DoConvert.2:
9000
 
    pop    af
9001
 
    or     $30
9002
 
    ld     (de), a
9003
 
    inc    de
9004
 
    djnz   _DoConvert.2
9005
 
 
9006
 
; Terminate string with NULL
9007
 
    xor    a
9008
 
    ld     (de), a
9009
 
 
9010
 
    ld h, d
9011
 
    ld l, e
9012
 
 
9013
 
    pop    bc
9014
 
    pop    de
9015
 
 
9016
 
    sbc hl, de
9017
 
    ld a, l           ; string size
9018
 
 
9019
 
    ret
9020
 
 
9021
 
endif
9022
 
 
9023
 
if defined MATH_FIN
9024
 
 
9025
 
;===============================================================
9026
 
; Convert a string of base-10 digits to a 16-bit value.
9027
 
; http://z80-heaven.wikidot.com/math#toc32
9028
 
;Input:
9029
 
;     DE points to the base 10 number string in RAM.
9030
 
;Outputs:
9031
 
;     HL is the 16-bit value of the number
9032
 
;     DE points to the byte after the number
9033
 
;     BC is HL/10
9034
 
;     z flag reset (nz)
9035
 
;     c flag reset (nc)
9036
 
;Destroys:
9037
 
;     A (actually, add 30h and you get the ending token)
9038
 
;Size:  23 bytes
9039
 
;Speed: 104n+42+11c
9040
 
;       n is the number of digits
9041
 
;       c is at most n-2
9042
 
;       at most 595 cycles for any 16-bit decimal value
9043
 
;===============================================================
9044
 
 
9045
 
StrToInt:
9046
 
     ld hl,0          ;  10 : 210000
9047
 
ConvLoop:             ;
9048
 
     ld a,(de)        ;   7 : 1A
9049
 
     sub 30h          ;   7 : D630
9050
 
     cp 10            ;   7 : FE0A
9051
 
     ret nc           ;5|11 : D0
9052
 
     inc de           ;   6 : 13
9053
 
                      ;
9054
 
     ld b,h           ;   4 : 44
9055
 
     ld c,l           ;   4 : 4D
9056
 
     add hl,hl        ;  11 : 29
9057
 
     add hl,hl        ;  11 : 29
9058
 
     add hl,bc        ;  11 : 09
9059
 
     add hl,hl        ;  11 : 29
9060
 
                      ;
9061
 
     add a,l          ;   4 : 85
9062
 
     ld l,a           ;   4 : 6F
9063
 
     jr nc,ConvLoop   ;12|23: 30EE
9064
 
     inc h            ; --- : 24
9065
 
     jr ConvLoop      ; --- : 18EB
9066
 
 
9067
 
endif
9068
 
 
9069
 
if defined IntToStr
9070
 
 
9071
 
; divides hl by c
9072
 
; return remainder in a
9073
 
; http://wikiti.brandonw.net/index.php?title=Z80_Routines:Math:Division
9074
 
div_hl_c:
9075
 
   push bc
9076
 
   xor  a
9077
 
   ld   b, 16
9078
 
div_hl_c.loop:
9079
 
   add  hl, hl
9080
 
   rla
9081
 
   jr   c, $+5
9082
 
   cp   c
9083
 
   jr   c, $+4
9084
 
   sub  c
9085
 
   inc  l
9086
 
   djnz div_hl_c.loop
9087
 
   pop bc
9088
 
   ret
9089
 
 
9090
 
endif
9091
 
 
9092
 
if defined DIV_EHL
9093
 
 
9094
 
; http://wikiti.brandonw.net/index.php?title=Z80_Routines:Math:Division#24.2F8_division
9095
 
div_ehl_d:
9096
 
   xor  a
9097
 
   ld   b, 24
9098
 
div_ehl_d.loop:
9099
 
   add  hl, hl
9100
 
   rl   e
9101
 
   rla
9102
 
   jr   c, $+5
9103
 
   cp   d
9104
 
   jr   c, $+4
9105
 
   sub  d
9106
 
   inc  l
9107
 
   djnz div_ehl_d.loop
9108
 
   ret
9109
 
 
9110
 
div_dehl_c:
9111
 
   push bc
9112
 
   xor  a
9113
 
   ld   b, 32
9114
 
div_dehl_c.loop:
9115
 
   add  hl, hl
9116
 
   rl   e
9117
 
   rl   d
9118
 
   rla
9119
 
   jr   c, $+5
9120
 
   cp   c
9121
 
   jr   c, $+4
9122
 
   sub  c
9123
 
   inc  l
9124
 
   djnz div_dehl_c.loop
9125
 
   pop bc
9126
 
   ret
9127
 
 
9128
 
endif
9129
 
 
9130
 
 
9131
 
 
9132
 
;---------------------------------------------------------------------------------------------------------
9133
 
; VARIABLES INITIALIZE
9134
 
;---------------------------------------------------------------------------------------------------------
9135
 
 
9136
 
INITIALIZE_DUMMY:
9137
 
    xor a
9138
 
    ld (VAR_DUMMY.COUNTER), a                    ; max circular queue = 8 dummys
9139
 
    ld hl, VAR_DUMMY.DATA                        ; start of variable dummy circular queue
9140
 
    ld (VAR_DUMMY.POINTER), hl
9141
 
    ld b, VAR_DUMMY.LENGTH
9142
 
    ld c, 0
9143
 
INITIALIZE_DUMMY.1:
9144
 
    ld (hl), a
9145
 
    inc hl
9146
 
    djnz INITIALIZE_DUMMY.1
9147
 
    ret
9148
 
 
9149
 
INITIALIZE_DATA:
9150
 
    ld hl, DATA_ITEMS
9151
 
    ld (BASIC_DATPTR), hl        ; next DATA pointer to use by READ command
9152
 
    ld hl, 0
9153
 
    ld (BASIC_DATLIN), hl        ; index of DATA item to use by READ command
9154
 
    ret
9155
 
 
9156
 
INITIALIZE_VARIABLES:
9157
 
    call INITIALIZE_DATA
9158
 
    call INITIALIZE_DUMMY
9159
 
 
9160
 
    if defined SCREEN
9161
 
       call gfxInitSpriteCollisionTable
9162
 
    endif
9163
 
 
9164
 
    ;if defined COMPILE_TO_ROM
9165
 
    ;   ld ix, BIOS_JIFFY            ; initialize rom clock
9166
 
    ;   di
9167
 
    ;     ld (ix), 0
9168
 
    ;     ld (ix+1), 0
9169
 
    ;   ei
9170
 
    ;endif
9171
 
 
9172
 
              ld hl, IDF_19
9173
 
              ld d, 2       ; any = default integer
9174
 
              ld c, 0       ; variable name 1 (variable number)
9175
 
              ld b, 0       ; variable name 2 (type flag=any)
9176
 
              call INIT_VAR ; variable initialize
9177
 
              ld hl, IDF_27
9178
 
              ld d, 2       ; any = default integer
9179
 
              ld c, 1       ; variable name 1 (variable number)
9180
 
              ld b, 0       ; variable name 2 (type flag=any)
9181
 
              call INIT_VAR ; variable initialize
9182
 
              ld hl, IDF_37
9183
 
              ld d, 2       ; any = default integer
9184
 
              ld c, 2       ; variable name 1 (variable number)
9185
 
              ld b, 0       ; variable name 2 (type flag=any)
9186
 
              call INIT_VAR ; variable initialize
9187
 
              ld hl, IDF_41
9188
 
              ld d, 2       ; any = default integer
9189
 
              ld c, 3       ; variable name 1 (variable number)
9190
 
              ld b, 0       ; variable name 2 (type flag=any)
9191
 
              call INIT_VAR ; variable initialize
9192
 
              ld hl, IDF_45
9193
 
              ld d, 2       ; any = default integer
9194
 
              ld c, 4       ; variable name 1 (variable number)
9195
 
              ld b, 0       ; variable name 2 (type flag=any)
9196
 
              call INIT_VAR ; variable initialize
9197
 
              ld hl, IDF_56
9198
 
              ld d, 2       ; any = default integer
9199
 
              ld c, 5       ; variable name 1 (variable number)
9200
 
              ld b, 0       ; variable name 2 (type flag=any)
9201
 
              call INIT_VAR ; variable initialize
9202
 
              ld hl, IDF_57
9203
 
              ld d, 2       ; any = default integer
9204
 
              ld c, 6       ; variable name 1 (variable number)
9205
 
              ld b, 0       ; variable name 2 (type flag=any)
9206
 
              call INIT_VAR ; variable initialize
9207
 
              ld hl, IDF_69
9208
 
              ld d, 2       ; any = default integer
9209
 
              ld c, 7       ; variable name 1 (variable number)
9210
 
              ld b, 0       ; variable name 2 (type flag=any)
9211
 
              call INIT_VAR ; variable initialize
9212
 
              ld hl, IDF_73
9213
 
              ld d, 2       ; any = default integer
9214
 
              ld c, 8       ; variable name 1 (variable number)
9215
 
              ld b, 0       ; variable name 2 (type flag=any)
9216
 
              call INIT_VAR ; variable initialize
9217
 
              ld hl, IDF_77
9218
 
              ld d, 2       ; any = default integer
9219
 
              ld c, 9       ; variable name 1 (variable number)
9220
 
              ld b, 0       ; variable name 2 (type flag=any)
9221
 
              call INIT_VAR ; variable initialize
9222
 
              ld hl, IDF_82
9223
 
              ld d, 2       ; any = default integer
9224
 
              ld c, 10      ; variable name 1 (variable number)
9225
 
              ld b, 0       ; variable name 2 (type flag=any)
9226
 
              call INIT_VAR ; variable initialize
9227
 
              ret
9228
 
 
9229
 
 
9230
 
;---------------------------------------------------------------------------------------------------------
9231
 
; MAIN WORK AREA - LITERALS / VARIABLES / CONFIGURATIONS
9232
 
;---------------------------------------------------------------------------------------------------------
9233
 
 
9234
 
if defined COMPILE_TO_ROM
9235
 
 
9236
 
   workAreaPad:
9237
 
   pgmPage1.pad: equ pageSize - (workAreaPad - pgmArea)
9238
 
 
9239
 
   if pgmPage1.pad >= 0
9240
 
      ds pgmPage1.pad, 0
9241
 
   ;else
9242
 
   ;   .WARNING "There's no free space left on program page 1"
9243
 
   endif
9244
 
 
9245
 
endif
9246
 
 
9247
 
VAR_STACK.START:     equ ramArea
9248
 
    ;VAR_STACK.END:       equ VAR_STACK.START + 0x800   ; 2kb (~200 variables)
9249
 
 
9250
 
VAR_STACK.POINTER:   equ VAR_STACK.START
9251
 
 
9252
 
PRINT.CRLF:      db 3, 0, 0, 2
9253
 
                 dw PRINT.CRLF.DATA, 0, 0, 0
9254
 
PRINT.CRLF.DATA: db 13,10,0
9255
 
 
9256
 
PRINT.TAB:       db 3, 0, 0, 1
9257
 
                 dw PRINT.TAB.DATA, 0, 0, 0
9258
 
PRINT.TAB.DATA:  db 09,0
9259
 
 
9260
 
; null double
9261
 
LIT_NULL_DBL: dw 0, 0, 0, 0
9262
 
 
9263
 
; null string
9264
 
LIT_NULL_STR: db 0
9265
 
 
9266
 
; quote string
9267
 
LIT_QUOTE_CHAR: db '\"'
9268
 
 
9269
 
; logical true
9270
 
LIT_TRUE: db 2, 0, 0
9271
 
          dw 0, 0xFFFF, 0, 0
9272
 
 
9273
 
; logical false
9274
 
LIT_FALSE: db 2, 0, 0
9275
 
           dw 0, 0, 0, 0
9276
 
 
9277
 
 
9278
 
; numerical literal
9279
 
LIT_4:   db 2, 0, 0
9280
 
      dw 0, 5, 0, 0
9281
 
 
9282
 
; numerical literal
9283
 
LIT_7:   db 2, 0, 0
9284
 
      dw 0, 0, 0, 0
9285
 
 
9286
 
; numerical literal
9287
 
LIT_8:   db 2, 0, 0
9288
 
      dw 0, 0, 0, 0
9289
 
 
9290
 
; numerical literal
9291
 
LIT_9:   db 2, 0, 0
9292
 
      dw 0, 255, 0, 0
9293
 
 
9294
 
; numerical literal
9295
 
LIT_10:   db 2, 0, 0
9296
 
      dw 0, 191, 0, 0
9297
 
 
9298
 
; numerical literal
9299
 
LIT_11:   db 2, 0, 0
9300
 
      dw 0, 2, 0, 0
9301
 
 
9302
 
; numerical literal
9303
 
LIT_12:   db 2, 0, 0
9304
 
      dw 0, 2, 0, 0
9305
 
 
9306
 
; numerical literal
9307
 
LIT_13:   db 2, 0, 0
9308
 
      dw 0, 127, 0, 0
9309
 
 
9310
 
; numerical literal
9311
 
LIT_14:   db 2, 0, 0
9312
 
      dw 0, 189, 0, 0
9313
 
 
9314
 
; numerical literal
9315
 
LIT_15:   db 2, 0, 0
9316
 
      dw 0, 129, 0, 0
9317
 
 
9318
 
; numerical literal
9319
 
LIT_16:   db 2, 0, 0
9320
 
      dw 0, 2, 0, 0
9321
 
 
9322
 
; numerical literal
9323
 
LIT_17:   db 2, 0, 0
9324
 
      dw 0, 253, 0, 0
9325
 
 
9326
 
; numerical literal
9327
 
LIT_18:   db 2, 0, 0
9328
 
      dw 0, 189, 0, 0
9329
 
 
9330
 
; identifier PI
9331
 
IDF_19:   equ VAR_STACK.POINTER + 0
9332
 
 
9333
 
; numerical literal
9334
 
LIT_21:   db 2, 0, 0
9335
 
      dw 0, 4, 0, 0
9336
 
 
9337
 
; numerical literal
9338
 
LIT_23:   db 2, 0, 0
9339
 
      dw 0, 1, 0, 0
9340
 
 
9341
 
; identifier A
9342
 
IDF_27:   equ VAR_STACK.POINTER + 11
9343
 
 
9344
 
; numerical literal
9345
 
LIT_28:   db 2, 0, 0
9346
 
      dw 0, 0, 0, 0
9347
 
 
9348
 
; numerical literal
9349
 
LIT_31:   db 2, 0, 0
9350
 
      dw 0, 2, 0, 0
9351
 
 
9352
 
; numerical literal
9353
 
LIT_32:   db 2, 0, 0
9354
 
      dw 0, 12, 0, 0
9355
 
 
9356
 
; numerical literal
9357
 
LIT_36:   db 2, 0, 0
9358
 
      dw 0, 2, 0, 0
9359
 
 
9360
 
; identifier B
9361
 
IDF_37:   equ VAR_STACK.POINTER + 22
9362
 
 
9363
 
; numerical literal
9364
 
LIT_38:   db 2, 0, 0
9365
 
      dw 0, 0, 0, 0
9366
 
 
9367
 
; numerical literal
9368
 
LIT_39:   db 2, 0, 0
9369
 
      dw 0, 30, 0, 0
9370
 
 
9371
 
; numerical literal
9372
 
LIT_40:   db 2, 0, 0
9373
 
      dw 0, 30, 0, 0
9374
 
 
9375
 
; identifier X
9376
 
IDF_41:   equ VAR_STACK.POINTER + 33
9377
 
 
9378
 
; numerical literal
9379
 
LIT_42:   db 2, 0, 0
9380
 
      dw 0, 63, 0, 0
9381
 
 
9382
 
; numerical literal
9383
 
LIT_43:   db 2, 0, 0
9384
 
      dw 0, 20, 0, 0
9385
 
 
9386
 
; identifier Y
9387
 
IDF_45:   equ VAR_STACK.POINTER + 44
9388
 
 
9389
 
; numerical literal
9390
 
LIT_46:   db 2, 0, 0
9391
 
      dw 0, 96, 0, 0
9392
 
 
9393
 
; numerical literal
9394
 
LIT_47:   db 2, 0, 0
9395
 
      dw 0, 20, 0, 0
9396
 
 
9397
 
; numerical literal
9398
 
LIT_50:   db 2, 0, 0
9399
 
      dw 0, 0, 0, 0
9400
 
 
9401
 
; numerical literal
9402
 
LIT_54:   db 2, 0, 0
9403
 
      dw 0, 90, 0, 0
9404
 
 
9405
 
; identifier X0
9406
 
IDF_56:   equ VAR_STACK.POINTER + 55
9407
 
 
9408
 
; identifier Y0
9409
 
IDF_57:   equ VAR_STACK.POINTER + 66
9410
 
 
9411
 
; numerical literal
9412
 
LIT_59:   db 2, 0, 0
9413
 
      dw 0, 15, 0, 0
9414
 
 
9415
 
; numerical literal
9416
 
LIT_61:   db 2, 0, 0
9417
 
      dw 0, 0, 0, 0
9418
 
 
9419
 
; numerical literal
9420
 
LIT_62:   db 2, 0, 0
9421
 
      dw 0, 2, 0, 0
9422
 
 
9423
 
; numerical literal
9424
 
LIT_63:   db 2, 0, 0
9425
 
      dw 0, 12, 0, 0
9426
 
 
9427
 
; numerical literal
9428
 
LIT_64:   db 2, 0, 0
9429
 
      dw 0, 2, 0, 0
9430
 
 
9431
 
; numerical literal
9432
 
LIT_65:   db 2, 0, 0
9433
 
      dw 0, 193, 0, 0
9434
 
 
9435
 
; numerical literal
9436
 
LIT_66:   db 2, 0, 0
9437
 
      dw 0, 50, 0, 0
9438
 
 
9439
 
; numerical literal
9440
 
LIT_67:   db 2, 0, 0
9441
 
      dw 0, 96, 0, 0
9442
 
 
9443
 
; numerical literal
9444
 
LIT_68:   db 2, 0, 0
9445
 
      dw 0, 50, 0, 0
9446
 
 
9447
 
; identifier X1
9448
 
IDF_69:   equ VAR_STACK.POINTER + 77
9449
 
 
9450
 
; numerical literal
9451
 
LIT_70:   db 2, 0, 0
9452
 
      dw 0, 193, 0, 0
9453
 
 
9454
 
; numerical literal
9455
 
LIT_71:   db 2, 0, 0
9456
 
      dw 0, 20, 0, 0
9457
 
 
9458
 
; numerical literal
9459
 
LIT_72:   db 2, 0, 0
9460
 
      dw 0, 12, 0, 0
9461
 
 
9462
 
; identifier Y1
9463
 
IDF_73:   equ VAR_STACK.POINTER + 88
9464
 
 
9465
 
; numerical literal
9466
 
LIT_74:   db 2, 0, 0
9467
 
      dw 0, 96, 0, 0
9468
 
 
9469
 
; numerical literal
9470
 
LIT_75:   db 2, 0, 0
9471
 
      dw 0, 20, 0, 0
9472
 
 
9473
 
; numerical literal
9474
 
LIT_76:   db 2, 0, 0
9475
 
      dw 0, 12, 0, 0
9476
 
 
9477
 
; identifier X2
9478
 
IDF_77:   equ VAR_STACK.POINTER + 99
9479
 
 
9480
 
; numerical literal
9481
 
LIT_78:   db 2, 0, 0
9482
 
      dw 0, 193, 0, 0
9483
 
 
9484
 
; numerical literal
9485
 
LIT_79:   db 2, 0, 0
9486
 
      dw 0, 20, 0, 0
9487
 
 
9488
 
; numerical literal
9489
 
LIT_80:   db 2, 0, 0
9490
 
      dw 0, 12, 0, 0
9491
 
 
9492
 
; identifier Y2
9493
 
IDF_82:   equ VAR_STACK.POINTER + 110
9494
 
 
9495
 
; numerical literal
9496
 
LIT_83:   db 2, 0, 0
9497
 
      dw 0, 96, 0, 0
9498
 
 
9499
 
; numerical literal
9500
 
LIT_84:   db 2, 0, 0
9501
 
      dw 0, 20, 0, 0
9502
 
 
9503
 
; numerical literal
9504
 
LIT_85:   db 2, 0, 0
9505
 
      dw 0, 12, 0, 0
9506
 
 
9507
 
; numerical literal
9508
 
LIT_86:   db 2, 0, 0
9509
 
      dw 0, 15, 0, 0
9510
 
 
9511
 
; numerical literal
9512
 
LIT_87:   db 2, 0, 0
9513
 
      dw 0, 15, 0, 0
9514
 
 
9515
 
; numerical literal
9516
 
LIT_88:   db 2, 0, 0
9517
 
      dw 0, 200, 0, 0
9518
 
 
9519
 
AFTER_LAST_VARIABLE:   equ VAR_STACK.POINTER + 121
9520
 
 
9521
 
VAR_DUMMY.START:       equ AFTER_LAST_VARIABLE    ; variable dummy circular queue area
9522
 
VAR_DUMMY.COUNTER:     equ VAR_DUMMY.START        ; variable dummy circular queue count
9523
 
VAR_DUMMY.POINTER:     equ VAR_DUMMY.COUNTER + 1  ; pointer to next variable dummy
9524
 
VAR_DUMMY.DATA:        equ VAR_DUMMY.POINTER + 2  ; first variable dummy
9525
 
 
9526
 
VAR_DUMMY.SIZE:        equ 8
9527
 
VAR_DUMMY.LENGTH:      equ (11 * VAR_DUMMY.SIZE)
9528
 
VAR_DUMMY.END:         equ VAR_DUMMY.DATA + VAR_DUMMY.LENGTH
9529
 
VAR_STACK.END:         equ VAR_DUMMY.END + 1
9530
 
 
9531
 
;--------------------------------------------------------
9532
 
; DATA SIMBOLS
9533
 
;--------------------------------------------------------
9534
 
 
9535
 
DATA_ITEMS:
9536
 
DATA_ITEMS_COUNT:   equ 0
9537
 
 
9538
 
DATA_SET_ITEMS_START:
9539
 
DATA_SET_ITEMS_COUNT:   equ 0
9540
 
 
9541
 
 
9542
 
;---------------------------------------------------------------------------------------------------------
9543
 
; PROGRAM FOOTER
9544
 
;---------------------------------------------------------------------------------------------------------
9545
 
 
9546
 
    if defined COMPILE_TO_ROM
9547
 
 
9548
 
        romPad:
9549
 
 
9550
 
        pgmPage2.pad: equ romSize - (romPad - pgmArea)
9551
 
 
9552
 
        if pgmPage2.pad >= 0
9553
 
           ds pgmPage2.pad, 0
9554
 
 
9555
 
           if pgmPage2.pad < lowLimitSize
9556
 
                .WARNING "There's only less than 5% free space on this ROM"
9557
 
           endif
9558
 
        else
9559
 
           .ERROR "There's no free space left on this ROM"
9560
 
        endif
9561
 
 
9562
 
    endif
9563
 
 
9564
 
    end_file: end start_pgm           ; label start is the entry point
9565