ugBASIC 1.18
An isomorphic BASIC language compiler for retrocomputers
Loading...
Searching...
No Matches
play_string.c
Go to the documentation of this file.
1/*****************************************************************************
2 * ugBASIC - an isomorphic BASIC language compiler for retrocomputers *
3 *****************************************************************************
4 * Copyright 2021-2026 Marco Spedaletti (asimov@mclink.it)
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *----------------------------------------------------------------------------
18 * Concesso in licenza secondo i termini della Licenza Apache, versione 2.0
19 * (la "Licenza"); è proibito usare questo file se non in conformità alla
20 * Licenza. Una copia della Licenza è disponibile all'indirizzo:
21 *
22 * http://www.apache.org/licenses/LICENSE-2.0
23 *
24 * Se non richiesto dalla legislazione vigente o concordato per iscritto,
25 * il software distribuito nei termini della Licenza è distribuito
26 * "COSÌ COM'È", SENZA GARANZIE O CONDIZIONI DI ALCUN TIPO, esplicite o
27 * implicite. Consultare la Licenza per il testo specifico che regola le
28 * autorizzazioni e le limitazioni previste dalla medesima.
29 ****************************************************************************/
30
31/****************************************************************************
32 * INCLUDE SECTION
33 ****************************************************************************/
34
35#include "../../ugbc.h"
36
37/****************************************************************************
38 * CODE SECTION
39 ****************************************************************************/
40
41/* <usermanual>
42@keyword PLAY (program)
43
44@english
45
46The ''PLAY'' allows you to generate music directly from your computer,
47turning it into a real musical instrument. The ''PLAY'' command uses
48a specific syntax to describe notes, duration, volume, and other
49musical parameters.
50
51Musical notes can be specified using the letters A through G, with numbers
52to indicate the octave, or a number from 1 to 9. The duration of a note can be specified
53with the letter L. To insert a rest, use the letter P. The octave can be
54specified with the letter O followed by a number. The tempo of the song can be
55changed with the T command, while the volume can be changed using the V letter.
56
57@italian
58
59Il comando ''PLAY'' ti consente di generare musica direttamente dal tuo computer,
60trasformandolo in un vero strumento musicale. Il comando ''PLAY'' utilizza una
61sintassi specifica per descrivere note, durata, volume e altri parametri musicali.
62
63Le note musicali possono essere specificate utilizzando le lettere dalla A alla G (o un numero da 1 a 9),
64con numeri per indicare l'ottava. La durata di una nota può essere specificata con
65la lettera L. Per inserire una pausa, utilizzare la lettera P. L'ottava può essere
66specificata con la lettera O seguita da un numero. Il tempo del brano può essere
67modificato con il comando T, mentre il volume può essere modificato utilizzando
68la lettera V.
69
70@syntax PLAY string
71
72@example PLAY "O1V31T2L4GGL8GGL4B-AAGGF+G"
73
74@usedInExample audio_play_02.bas
75
76</usermanual> */
77void play_string( Environment * _environment, char * _string ) {
78
79 if ( _environment->emptyProcedure ) {
80 return;
81 }
82
84
86
87 char doneCommandLabel[MAX_TEMPORARY_STORAGE]; sprintf( doneCommandLabel, "%sdone", label );
88 char duration4CommandLabel[MAX_TEMPORARY_STORAGE]; sprintf( duration4CommandLabel, "%sduration4", label );
89 char duration4DefaultLabel[MAX_TEMPORARY_STORAGE]; sprintf( duration4DefaultLabel, "%sduration4d", label );
90 char durationCommandLabel[MAX_TEMPORARY_STORAGE]; sprintf( durationCommandLabel, "%sdurationc", label );
91 char durationDoneCommandLabel[MAX_TEMPORARY_STORAGE]; sprintf( durationDoneCommandLabel, "%sdonec", label );
92 char durationDotCommandLabel[MAX_TEMPORARY_STORAGE]; sprintf( durationDotCommandLabel, "%sdot", label );
93 char note2CommandLabel[MAX_TEMPORARY_STORAGE]; sprintf( note2CommandLabel, "%snote2", label );
94 char noteACommandLabel[MAX_TEMPORARY_STORAGE]; sprintf( noteACommandLabel, "%snotea", label );
95 char noteBCommandLabel[MAX_TEMPORARY_STORAGE]; sprintf( noteBCommandLabel, "%snoteb", label );
96 char noteCCommandLabel[MAX_TEMPORARY_STORAGE]; sprintf( noteCCommandLabel, "%snotec", label );
97 char noteCommandLabel[MAX_TEMPORARY_STORAGE]; sprintf( noteCommandLabel, "%snote1", label );
98 char noteDCommandLabel[MAX_TEMPORARY_STORAGE]; sprintf( noteDCommandLabel, "%snoted", label );
99 char noteECommandLabel[MAX_TEMPORARY_STORAGE]; sprintf( noteECommandLabel, "%snotee", label );
100 char noteFCommandLabel[MAX_TEMPORARY_STORAGE]; sprintf( noteFCommandLabel, "%snotef", label );
101 char NoteFlatCommandLabel[MAX_TEMPORARY_STORAGE]; sprintf( NoteFlatCommandLabel, "%snoteflat", label );
102 char noteGCommandLabel[MAX_TEMPORARY_STORAGE]; sprintf( noteGCommandLabel, "%snoteg", label );
103 char NoteHashCommandLabel[MAX_TEMPORARY_STORAGE]; sprintf( NoteHashCommandLabel, "%snotehash", label );
104 char noteNCommandLabel[MAX_TEMPORARY_STORAGE]; sprintf( noteNCommandLabel, "%snoten", label );
105 char noteNxCommandLabel[MAX_TEMPORARY_STORAGE]; sprintf( noteNxCommandLabel, "%snotenx", label );
106 char octave2DefaultLabel[MAX_TEMPORARY_STORAGE]; sprintf( octave2DefaultLabel, "%soctave2", label );
107 char octaveCommandLabel[MAX_TEMPORARY_STORAGE]; sprintf( octaveCommandLabel, "%soctave", label );
108 char pause2CommandLabel[MAX_TEMPORARY_STORAGE]; sprintf( pause2CommandLabel, "%spause2", label );
109 char pauseCommandLabel[MAX_TEMPORARY_STORAGE]; sprintf( pauseCommandLabel, "%spause", label );
110 char playCommandLabel[MAX_TEMPORARY_STORAGE]; sprintf( playCommandLabel, "%splaycommand", label );
111 char playStringLabel[MAX_TEMPORARY_STORAGE]; sprintf( playStringLabel, "%splaystring", label );
112 char readParameter2DoneLabel[MAX_TEMPORARY_STORAGE]; sprintf( readParameter2DoneLabel, "%spar2done", label );
113 char readParameter2Label[MAX_TEMPORARY_STORAGE]; sprintf( readParameter2Label, "%spar2", label );
114 char readParameter3Label[MAX_TEMPORARY_STORAGE]; sprintf( readParameter3Label, "%spar3", label );
115 char readParameterAdd1[MAX_TEMPORARY_STORAGE]; sprintf( readParameterAdd1, "%sparadd1", label );
116 char readParameterDiv2[MAX_TEMPORARY_STORAGE]; sprintf( readParameterDiv2, "%spardiv2", label );
117 char readParameterLabel[MAX_TEMPORARY_STORAGE]; sprintf( readParameterLabel, "%spar", label );
118 char readParameterMul2[MAX_TEMPORARY_STORAGE]; sprintf( readParameterMul2, "%sparmul2", label );
119 char readParameterSub1[MAX_TEMPORARY_STORAGE]; sprintf( readParameterSub1, "%sparsub1", label );
120 char tempo2DefaultLabel[MAX_TEMPORARY_STORAGE]; sprintf( tempo2DefaultLabel, "%stempo2", label );
121 char tempoCommandLabel[MAX_TEMPORARY_STORAGE]; sprintf( tempoCommandLabel, "%stempo", label );
122 char volume15DefaultLabel[MAX_TEMPORARY_STORAGE]; sprintf( volume15DefaultLabel, "%svolume15", label );
123 char volumeCommandLabel[MAX_TEMPORARY_STORAGE]; sprintf( volumeCommandLabel, "%svolume", label );
124
125 // Move to the start of routine
126 cpu_jump( _environment, playStringLabel );
127
128 // ----------------------------[ SUBROUTINE: READ PARAMETER ]
129
130 // string -> (address, size)
131 Variable * address = variable_temporary( _environment, VT_ADDRESS, "(address)" );
132 Variable * size = variable_temporary( _environment, VT_BYTE, "(address)" );
133
134 // xxx, -> (paddress, psize)
135 Variable * paddress = variable_temporary( _environment, VT_ADDRESS, "(address)" );
136 Variable * psize = variable_temporary( _environment, VT_BYTE, "(size)" );
137 Variable * digit = variable_temporary( _environment, VT_BYTE, "(digit)" );
138 Variable * parameter = variable_temporary( _environment, VT_POSITION, "(parameter)" );
139 Variable * eos = variable_temporary( _environment, VT_BYTE, "(eos)" );
140
141 cpu_label( _environment, readParameterLabel );
142
143 // Take current address as starting of parameter
144 cpu_move_16bit( _environment, address->realName, paddress->realName );
145
146 // The parameter starts with a zero length.
147 cpu_store_8bit( _environment, psize->realName, 0 );
148
149 // You can use one of the following
150 // suffixes instead of adding a numeral:
151 // Suffix Purpose
152 // + Adds 1 to the current value.
153 // Subtracts 1 from the current value.
154 // > Multiplies the current value by 2.
155 // < Divides the current value by 2.
156
157 cpu_move_8bit_indirect2( _environment, address->realName, digit->realName );
158 cpu_compare_and_branch_8bit_const( _environment, digit->realName, '+', readParameterAdd1, 1 );
159 cpu_compare_and_branch_8bit_const( _environment, digit->realName, '-', readParameterSub1, 1 );
160 cpu_compare_and_branch_8bit_const( _environment, digit->realName, '>', readParameterMul2, 1 );
161 cpu_compare_and_branch_8bit_const( _environment, digit->realName, '<', readParameterDiv2, 1 );
162
163 // Let's retrieve the parameter. We know that the parameter should end
164 // with a ',' so we are looking for that character, or for the end
165 // of the original string, as well -- note that the end of the string
166 // means end of the parameter itself.
167 begin_do_loop( _environment );
168
169 // Exit if playing string is ended
170 cpu_compare_and_branch_8bit_const( _environment, size->realName, 0, readParameter2Label, 1 );
171
172 // Exit from this loop if the letter is not a digit.
173 cpu_move_8bit_indirect2( _environment, address->realName, digit->realName );
174 cpu_greater_than_8bit_const( _environment, digit->realName, '9', eos->realName, 0, 0 );
175 cpu_compare_and_branch_8bit_const( _environment, eos->realName, 0xff, readParameter3Label, 1 );
176 cpu_less_than_8bit_const( _environment, digit->realName, '0', eos->realName, 0, 0 );
177 cpu_compare_and_branch_8bit_const( _environment, eos->realName, 0xff, readParameter3Label, 1 );
178
179 cpu_dec( _environment, size->realName );
180 cpu_inc_16bit( _environment, address->realName );
181
182 // Increment the length of the parameter, and move along the
183 // playing commands string
184 cpu_inc( _environment, psize->realName );
185
186 end_do_loop( _environment );
187
188 cpu_label( _environment, readParameter3Label );
189
190 // If we arrived here, it means that we are able to read and decode
191 // the parameter as number.
192 cpu_label( _environment, readParameter2Label );
193 cpu_convert_string_into_8bit( _environment, paddress->realName, psize->realName, parameter->realName );
194
195 cpu_return( _environment );
196
197 cpu_label( _environment, readParameterAdd1 );
198 cpu_inc( _environment, parameter->realName );
199 cpu_jump( _environment, readParameter2DoneLabel );
200
201 cpu_label( _environment, readParameterSub1 );
202 cpu_dec( _environment, parameter->realName );
203 cpu_jump( _environment, readParameter2DoneLabel );
204
205 cpu_label( _environment, readParameterMul2 );
206 cpu_math_mul2_const_8bit( _environment, parameter->realName, 1, 0 );
207 cpu_jump( _environment, readParameter2DoneLabel );
208
209 cpu_label( _environment, readParameterDiv2 );
210 cpu_math_div2_const_8bit( _environment, parameter->realName, 1, 0, NULL );
211 cpu_jump( _environment, readParameter2DoneLabel );
212
213 cpu_label( _environment, readParameter2DoneLabel );
214 cpu_dec( _environment, size->realName );
215 cpu_inc_16bit( _environment, address->realName );
216 cpu_inc( _environment, psize->realName );
217 cpu_return( _environment );
218
219 // ------------------------------------ STARTING ROUTINE
220 cpu_label( _environment, playStringLabel );
221
222 // Temporary variable
223 Variable * temp = variable_temporary( _environment, VT_BYTE, "(temp)" );
224 Variable * remainder = variable_temporary( _environment, VT_BYTE, "(remainder)" );
225
226 // String with the playing commands,
227 Variable * string = variable_define( _environment, "playstring__string", VT_DSTRING, 0 );
228
229 // Letter with command
230 Variable * command = variable_temporary( _environment, VT_BYTE, "(command)" );
231
232 // Note
233 Variable * note8 = variable_temporary( _environment, VT_BYTE, "(note8)" );
234 Variable * note16 = variable_temporary( _environment, VT_WORD, "(note16)" );
235 Variable * duration16 = variable_temporary( _environment, VT_WORD, "(duration16)" );
236
237 // Octave.
238 Variable * octave = variable_retrieve( _environment, "PLAYOCTAVE" );
239
240 // Duration
241 Variable * duration = variable_retrieve( _environment, "PLAYDURATION" );
242
243 // Tempo
244 Variable * tempo = variable_retrieve( _environment, "PLAYTEMPO" );
245
246 // Period and periodEquivalent
247 Variable * period = variable_temporary( _environment, VT_BYTE, "(period)" );
248 variable_store( _environment, period->name, 0xff );
249 Variable * periodEquivalent = variable_temporary( _environment, VT_BYTE, "(periodEquivalent)" );
250 cpu_math_div_8bit_to_8bit( _environment, period->realName, tempo->realName, periodEquivalent->realName, remainder->realName, 0 );
251
252 // Volume
253 Variable * volume = variable_retrieve( _environment, "PLAYVOLUME" );
254
255 // Retrieve the effective address of the string with the playing commands.
256
257 cpu_dsdescriptor( _environment, string->realName, address->realName, size->realName );
258
259 // ------------------------------------ FETCH AND DECODE LOOP
260 begin_do_loop( _environment );
261
262 // Are playing commands ended? Exit fetch and decode loop.
263 cpu_compare_and_branch_8bit_const( _environment, size->realName, 0, label, 1 );
264
265 // Retrieve command letter.
266 outline0("; command = ...");
267
268 cpu_move_8bit_indirect2( _environment, address->realName, command->realName );
269 cpu_dec( _environment, size->realName );
270 cpu_inc_16bit( _environment, address->realName );
271
272 // Is it 'O' ? -> OCTAVE
273 cpu_compare_and_branch_char_const( _environment, command->realName, 'O', octaveCommandLabel, 1 );
274
275 // Is it 'L' ? -> DURATION
276 cpu_compare_and_branch_char_const( _environment, command->realName, 'L', durationCommandLabel, 1 );
277
278 // Is it 'T' ? -> TEMPO
279 cpu_compare_and_branch_char_const( _environment, command->realName, 'T', tempoCommandLabel, 1 );
280
281 // Is it 'V' ? -> VOLUME
282 cpu_compare_and_branch_char_const( _environment, command->realName, 'V', volumeCommandLabel, 1 );
283
284 // Is it 'P' ? -> PAUSE
285 cpu_compare_and_branch_char_const( _environment, command->realName, 'P', pauseCommandLabel, 1 );
286
287 // Is it 'A'-'G' ? -> NOTE A-G
288 cpu_compare_and_branch_char_const( _environment, command->realName, 'A', noteACommandLabel, 1 );
289 cpu_compare_and_branch_char_const( _environment, command->realName, 'B', noteBCommandLabel, 1 );
290 cpu_compare_and_branch_char_const( _environment, command->realName, 'C', noteCCommandLabel, 1 );
291 cpu_compare_and_branch_char_const( _environment, command->realName, 'D', noteDCommandLabel, 1 );
292 cpu_compare_and_branch_char_const( _environment, command->realName, 'E', noteECommandLabel, 1 );
293 cpu_compare_and_branch_char_const( _environment, command->realName, 'F', noteFCommandLabel, 1 );
294 cpu_compare_and_branch_char_const( _environment, command->realName, 'G', noteGCommandLabel, 1 );
295
296 // Is it '1'-'9'? -> NOTE A-G in numeric notation
297 cpu_compare_and_branch_char_const( _environment, command->realName, 'N', noteNxCommandLabel, 1 );
298 cpu_compare_and_branch_char_const( _environment, command->realName, '1', noteNCommandLabel, 1 );
299 cpu_compare_and_branch_char_const( _environment, command->realName, '2', noteNCommandLabel, 1 );
300 cpu_compare_and_branch_char_const( _environment, command->realName, '3', noteNCommandLabel, 1 );
301 cpu_compare_and_branch_char_const( _environment, command->realName, '4', noteNCommandLabel, 1 );
302 cpu_compare_and_branch_char_const( _environment, command->realName, '5', noteNCommandLabel, 1 );
303 cpu_compare_and_branch_char_const( _environment, command->realName, '6', noteNCommandLabel, 1 );
304 cpu_compare_and_branch_char_const( _environment, command->realName, '7', noteNCommandLabel, 1 );
305 cpu_compare_and_branch_char_const( _environment, command->realName, '8', noteNCommandLabel, 1 );
306 cpu_compare_and_branch_char_const( _environment, command->realName, '9', noteNCommandLabel, 1 );
307
308 // No command was recognized: silently, move to the next character.
309 cpu_jump( _environment, doneCommandLabel );
310
311 // ----------------------------[ OCTAVE ]
312
313 // Our single octave (Octdve 2) sounds fine, but, variety being
314 // the spice of music as well as Irish stely, it gets a little
315 // boring when played over and over (like a piano with only 12 keys).
316 // To change octaves, use the letter O followed by a number in the range
317 // 1 to 5. If you don't specify the octave, the computer automatically
318 // uses Octave 2 (O2), which includes middle-C.
319
320 cpu_label( _environment, octaveCommandLabel );
321 cpu_move_8bit( _environment, octave->realName, parameter->realName );
322 cpu_call( _environment, readParameterLabel );
323 cpu_compare_and_branch_8bit_const( _environment, psize->realName, 0, octave2DefaultLabel, 1 );
324
325 cpu_move_8bit( _environment, parameter->realName, octave->realName );
326
327 cpu_jump( _environment, playCommandLabel );
328
329 cpu_label( _environment, octave2DefaultLabel );
330 cpu_store_8bit( _environment, parameter->realName, 2 );
331
332 cpu_jump( _environment, playCommandLabel );
333
334 // ----------------------------[ DURATION ]
335
336 // The computer automatically uses quarter notes, the initial
337 // "current value" for duration. To choose the note-length,
338 // use L followed by a number from 1 to 255. The number 1,
339 // for instance, denotes a whole note, 2 a half note,
340 // 4 a quarter note, 8 an eighth note, 16 a sixteenth note,
341 // and so on. In fact, you can use any number from 1 to 255.
342
343 cpu_label( _environment, durationCommandLabel );
344
345 // cpu_move_8bit( _environment, duration->realName, parameter->realName );
346 cpu_call( _environment, readParameterLabel );
347 cpu_compare_and_branch_8bit_const( _environment, psize->realName, 0, duration4DefaultLabel, 1 );
348
349 cpu_label( _environment, duration4CommandLabel );
350
351 cpu_math_div_8bit_to_8bit( _environment, periodEquivalent->realName, parameter->realName, duration->realName, remainder->realName, 0 );
352
353 // If you read music, you already know about "dotted notes." The dot tells
354 // you to increase the length of the note by one half its normal value. For
355 // example, a dotted quarter note is equal to a "3/8" note.
356 // You can play such a note by adding a period) or a series of periods
357 // (...) to the number. Each period increases the note-length by 1/2 its
358 // normal value. For example:
359
360 cpu_label( _environment, durationDotCommandLabel );
361
362 cpu_move_8bit_indirect2( _environment, address->realName, command->realName );
363 cpu_compare_and_branch_char_const( _environment, command->realName, '.', durationDoneCommandLabel, 0 );
364 cpu_dec( _environment, size->realName );
365 cpu_inc_16bit( _environment, address->realName );
366
367 cpu_move_8bit( _environment, duration->realName, temp->realName );
368 cpu_math_div2_const_8bit( _environment, temp->realName, 1, 0, NULL );
369 cpu_math_add_8bit( _environment, duration->realName, temp->realName, duration->realName );
370
371 cpu_jump( _environment, durationDotCommandLabel );
372
373 cpu_label( _environment, durationDoneCommandLabel );
374 cpu_jump( _environment, playCommandLabel );
375
376 cpu_label( _environment, duration4DefaultLabel );
377 cpu_store_8bit( _environment, duration->realName, 4 );
378 cpu_jump( _environment, duration4CommandLabel );
379
380 // ----------------------------[ TEMPO ]
381
382 // You can increase or decrease the tempo with T and a
383 // number from 1 to 255.11 You don't specify a tempo,
384 // your computer automatically uses T2.
385
386 cpu_label( _environment, tempoCommandLabel );
387
388 // cpu_move_8bit( _environment, tempo->realName, parameter->realName );
389 cpu_call( _environment, readParameterLabel );
390 cpu_compare_and_branch_8bit_const( _environment, psize->realName, 0, tempo2DefaultLabel, 1 );
391 cpu_move_8bit( _environment, parameter->realName, tempo->realName );
392 cpu_math_div_8bit_to_8bit( _environment, period->realName, parameter->realName, periodEquivalent->realName, remainder->realName, 0 );
393
394 cpu_jump( _environment, playCommandLabel );
395
396 cpu_label( _environment, tempo2DefaultLabel );
397 cpu_store_8bit( _environment, tempo->realName, 2 );
398 cpu_store_8bit( _environment, periodEquivalent->realName, 0x80 );
399
400 cpu_jump( _environment, playCommandLabel );
401
402 // ----------------------------[ VOLUME ]
403
404 // Sure, you can adjust the volume of your music by using the TV volume
405 // control, but who wants to sit by the set all of the time? Especially when the
406 // computer can adjust the volume for you.
407 // Yourcornputer does this with the V (volume) feature. All you need to do is
408 // use V followed by a numeral between 0 and 31. If you don't specify the
409 // value of V, your computer automatically uses V15.
410
411 cpu_label( _environment, volumeCommandLabel );
412
413 cpu_move_8bit( _environment, volume->realName, parameter->realName );
414 cpu_call( _environment, readParameterLabel );
415 cpu_compare_and_branch_8bit_const( _environment, psize->realName, 0, volume15DefaultLabel, 1 );
416
417 cpu_move_8bit( _environment, parameter->realName, volume->realName );
418
419 cpu_jump( _environment, playCommandLabel );
420
421 cpu_label( _environment, volume15DefaultLabel );
422 cpu_store_8bit( _environment, volume->realName, 15 );
423 cpu_jump( _environment, playCommandLabel );
424
425 // ----------------------------[ PAUSE ]
426
427 // To put a pause between notes, use P followed by a number from 1 to 255.
428 // Pause-lengths correspond to note-lengths with one important difference.
429 // You can't use dots (periods) with P. To compensate, just type a series of
430 // pauses. For example, to get a 3/8 pause, type P4P8 (= 1/4 + 1/8)
431
432 cpu_label( _environment, pauseCommandLabel );
433
434 cpu_call( _environment, readParameterLabel );
435
436 cpu_math_div_8bit_to_8bit( _environment, period->realName, parameter->realName, temp->realName, remainder->realName, 0 );
437 cpu_label( _environment, pause2CommandLabel );
438 wait_milliseconds_var( _environment, periodEquivalent->name );
439 cpu_dec( _environment, temp->realName );
440 cpu_compare_and_branch_8bit_const( _environment, temp->realName, 0, pause2CommandLabel, 0 );
441
442 cpu_jump( _environment, playCommandLabel );
443
444 // ----------------------------[ NOTE (numeric) ]
445
446 cpu_label( _environment, noteNCommandLabel );
447
448 cpu_dec_16bit( _environment, address->realName );
449 cpu_inc( _environment, size->realName );
450
451 cpu_label( _environment, noteNxCommandLabel );
452
453 cpu_call( _environment, readParameterLabel );
454
455 cpu_move_8bit( _environment, parameter->realName, temp->realName );
456
457 cpu_jump( _environment, note2CommandLabel );
458
459 // ----------------------------[ NOTE ]
460
461 cpu_label( _environment, noteACommandLabel );
462 cpu_store_8bit( _environment, temp->realName, 9 );
463 cpu_jump( _environment, noteCommandLabel );
464
465 cpu_label( _environment, noteBCommandLabel );
466 cpu_store_8bit( _environment, temp->realName, 11 );
467 cpu_jump( _environment, noteCommandLabel );
468
469 cpu_label( _environment, noteCCommandLabel );
470 cpu_store_8bit( _environment, temp->realName, 0 );
471 cpu_jump( _environment, noteCommandLabel );
472
473 cpu_label( _environment, noteDCommandLabel );
474 cpu_store_8bit( _environment, temp->realName, 2 );
475 cpu_jump( _environment, noteCommandLabel );
476
477 cpu_label( _environment, noteECommandLabel );
478 cpu_store_8bit( _environment, temp->realName, 4 );
479 cpu_jump( _environment, noteCommandLabel );
480
481 cpu_label( _environment, noteFCommandLabel );
482 cpu_store_8bit( _environment, temp->realName, 5 );
483 cpu_jump( _environment, noteCommandLabel );
484
485 cpu_label( _environment, noteGCommandLabel );
486 cpu_store_8bit( _environment, temp->realName, 7 );
487 cpu_jump( _environment, noteCommandLabel );
488
489 // The first-and probably easier-way to play the
490 // note you want is to enter one of the standard
491 // musical notes-A, B, C, D, E, For G.
492
493 cpu_label( _environment, noteCommandLabel );
494
495 cpu_move_8bit_indirect2( _environment, address->realName, parameter->realName );
496 // To indicate a
497 // sharp note, follow the note with a plus sign (+) or with the
498 // pound sign (#).
499 cpu_compare_and_branch_char_const( _environment, parameter->realName, '#', NoteHashCommandLabel, 1 );
500 cpu_compare_and_branch_char_const( _environment, parameter->realName, '+', NoteHashCommandLabel, 1 );
501 // To indicate a flat, follow it with a minus sign (~).
502 cpu_compare_and_branch_char_const( _environment, parameter->realName, '-', NoteFlatCommandLabel, 1 );
503 cpu_jump( _environment, note2CommandLabel );
504
505 // To indicate a
506 // sharp note, follow the note with a plus sign (+) or with the
507 // pound sign (#).
508
509 cpu_label( _environment, NoteHashCommandLabel );
510 cpu_inc( _environment, temp->realName );
511 cpu_inc_16bit( _environment, address->realName );
512 cpu_jump( _environment, note2CommandLabel );
513
514 // To indicate a flat, follow it with a minus sign (~).
515
516 cpu_label( _environment, NoteFlatCommandLabel );
517 cpu_dec( _environment, temp->realName );
518 cpu_inc_16bit( _environment, address->realName );
519 cpu_jump( _environment, note2CommandLabel );
520
521 cpu_label( _environment, note2CommandLabel );
522 cpu_store_8bit( _environment, note8->realName, 12 );
523 cpu_math_mul_8bit_to_16bit( _environment, note8->realName, octave->realName, note16->realName, 0 );
524 cpu_math_add_16bit_with_8bit( _environment, note16->realName, temp->realName, note16->realName );
525 cpu_math_mul_8bit_to_16bit( _environment, duration->realName, periodEquivalent->realName, duration16->realName, 0 );
526
527 // For example, A represents A natural; A# is A sharp; and A- is A flat.
528
529 bell_vars( _environment, note16->name, duration16->name, NULL, 1 );
530
531 cpu_label( _environment, playCommandLabel );
532
533 cpu_label( _environment, doneCommandLabel );
534
535 end_do_loop( _environment );
536 // ------------------------------------ FETCH AND DECODE LOOP (end)
537
538 cpu_label( _environment, label );
539 cpu_return( _environment );
540
542
543 Variable * string = variable_retrieve( _environment, _string );
544
545 if ( ( string->type != VT_STRING ) && ( string->type != VT_DSTRING ) ) {
547 }
548
549 if( string->type == VT_STRING ) {
550 Variable * dstring = variable_temporary( _environment, VT_DSTRING, "(dstring)" );
551 cpu_dsdefine( _environment, string->realName, dstring->realName );
552 string = dstring;
553 }
554
555 Variable * parameter = variable_retrieve( _environment, "playstring__string" );
556
557 variable_move( _environment, string->name, parameter->name );
558 cpu_call( _environment, "lib_play_string");
559
560 if ( _environment->procedureName ) {
561 yield( _environment );
562 }
563
564}
void cpu_math_mul2_const_8bit(Environment *_environment, char *_source, int _steps, int _signed)
CPU 6309: emit code to double for several times a 8 bit value
Definition 6309.c:1397
void cpu_math_add_16bit_with_8bit(Environment *_environment, char *_source, char *_destination, char *_other)
Definition 6309.c:1708
void cpu_math_div2_const_8bit(Environment *_environment, char *_source, int _steps, int _signed, char *_remainder)
CPU 6309: emit code to halves for several times a 8 bit value
Definition 6309.c:1329
void cpu_math_add_8bit(Environment *_environment, char *_source, char *_destination, char *_other)
CPU 6309: emit code to add two 8 bit values
Definition 6309.c:1017
void cpu_dec_16bit(Environment *_environment, char *_variable)
Definition 6309.c:4640
void cpu_inc(Environment *_environment, char *_variable)
Definition 6309.c:4555
void cpu_dsdefine(Environment *_environment, char *_string, char *_index)
Definition 6309.c:5884
void cpu_math_mul_8bit_to_16bit(Environment *_environment, char *_source, char *_destination, char *_other, int _signed)
CPU 6309: emit code to multiply two 8bit values in a 16 bit register
Definition 6309.c:1088
void cpu_compare_and_branch_char_const(Environment *_environment, char *_source, int _destination, char *_label, int _positive)
CPU 6309: emit code to compare two 8 bit values and jump if they are equal/different
Definition 6309.c:925
void cpu_label(Environment *_environment, char *_label)
Definition 6309.c:356
void cpu_dec(Environment *_environment, char *_variable)
Definition 6309.c:4630
void cpu_greater_than_8bit_const(Environment *_environment, char *_source, int _destination, char *_other, int _equal, int _signed)
Definition 6309.c:999
void cpu_move_16bit(Environment *_environment, char *_source, char *_destination)
CPU 6309: emit code to move 16 bit
Definition 6309.c:1474
void cpu_call(Environment *_environment, char *_label)
Definition 6309.c:3755
void cpu_store_8bit(Environment *_environment, char *_destination, int _value)
CPU 6309: emit code to store 8 bit
Definition 6309.c:761
void cpu_jump(Environment *_environment, char *_label)
Definition 6309.c:3739
void cpu_less_than_8bit_const(Environment *_environment, char *_source, int _destination, char *_other, int _equal, int _signed)
Definition 6309.c:960
void cpu_return(Environment *_environment)
Definition 6309.c:4030
void cpu_move_8bit_indirect2(Environment *_environment, char *_value, char *_source)
Definition 6309.c:5294
void cpu_convert_string_into_8bit(Environment *_environment, char *_string, char *_len, char *_value)
Definition 6309.c:5487
void cpu_inc_16bit(Environment *_environment, char *_variable)
Definition 6309.c:4565
void cpu_move_8bit(Environment *_environment, char *_source, char *_destination)
CPU 6309: emit code to move 8 bit
Definition 6309.c:743
void cpu_math_div_8bit_to_8bit(Environment *_environment, char *_source, char *_destination, char *_other, char *_other_remainder, int _signed)
Definition 6309.c:1163
void cpu_dsdescriptor(Environment *_environment, char *_index, char *_address, char *_size)
Definition 6309.c:5977
void cpu_compare_and_branch_8bit_const(Environment *_environment, char *_source, int _destination, char *_label, int _positive)
CPU 6309: emit code to compare two 8 bit values and jump if they are equal/different
Definition 6309.c:876
Variable * variable_retrieve(Environment *_environment, char *_name)
Variable * variable_move(Environment *_environment, char *_source, char *_destination)
Store the value of a variable inside another variable by converting it.
Variable * variable_define(Environment *_environment, char *_name, VariableType _type, int _value)
Define a variable for the program.
Variable * variable_temporary(Environment *_environment, VariableType _type, char *_meaning)
Define a temporary variable.
Variable * variable_store(Environment *_environment, char *_destination, unsigned int _value)
Store a direct value to a variable.
int size
Definition _optimizer.c:678
void bell_vars(Environment *_environment, char *_note, char *_duration, char *_channels, int _sync)
Emit ASM code for BELL ....
Definition bell.c:86
void volume(Environment *_environment, int _volume, int _channels)
Emit ASM code for VOLUME ....
Definition volume.c:70
void begin_do_loop(Environment *_environment)
Emit ASM code for DO ....
void end_do_loop(Environment *_environment)
Emit ASM code for ... LOOP.
Definition end_do_loop.c:49
void play_string(Environment *_environment, char *_string)
Definition play_string.c:77
char * procedureName
Definition ugbc.h:2775
int emptyProcedure
Definition ugbc.h:2932
char * name
Definition ugbc.h:979
VariableType type
Definition ugbc.h:988
char * realName
Definition ugbc.h:982
#define deploy_end(s)
Definition ugbc.h:4365
#define MAX_TEMPORARY_STORAGE
Definition ugbc.h:563
struct _Variable Variable
Structure of a single variable.
struct _Environment Environment
Structure of compilation environment.
@ VT_WORD
Definition ugbc.h:455
@ VT_POSITION
Definition ugbc.h:468
@ VT_STRING
Definition ugbc.h:474
@ VT_BYTE
Definition ugbc.h:450
@ VT_ADDRESS
Definition ugbc.h:465
@ VT_DSTRING
Definition ugbc.h:483
#define outline0(s)
Definition ugbc.h:4252
#define CRITICAL_CANNOT_USE_PLAY_WITHOUT_STRING(t)
Definition ugbc.h:3685
#define deploy_begin(s)
Definition ugbc.h:4356
#define MAKE_LABEL
Definition ugbc.h:3351
void wait_milliseconds_var(Environment *_environment, char *_timing)
Emit ASM code for WAIT [expression] MILLISECONDS.
void yield(Environment *_environment)
Emit code for YIELD.
Definition yield.c:63