7553 lines
560 KiB
Plaintext
7553 lines
560 KiB
Plaintext
* source: C:\Users\peter.russell\Documents\Personal\multiply\Contrib\psr\multiply\sys\ROM.asm.py
|
|
169 if __name__ == '__main__': enableListing()
|
|
170 #-----------------------------------------------------------------------
|
|
171 #
|
|
172 # Start of core
|
|
173 #
|
|
174 #-----------------------------------------------------------------------
|
|
175
|
|
176 # Pre-loading the formal interface as a way to get warnings when
|
|
177 # accidentally redefined with a different value
|
|
178 #
|
|
179 loadBindings(repo_root / 'interface.json')
|
|
180 loadBindings(repo_root / 'Core' / 'interface-dev.json') # Provisional values for DEVROM
|
|
181
|
|
182 # Gigatron clock
|
|
183 cpuClock = 6.250e+06
|
|
184
|
|
185 # Output pin assignment for VGA
|
|
186 R, G, B, hSync, vSync = 1, 4, 16, 64, 128
|
|
187 syncBits = hSync+vSync # Both pulses negative
|
|
188
|
|
189 # When the XOUT register is in the circuit, the rising edge triggers its update.
|
|
190 # The loop can therefore not be agnostic to the horizontal pulse polarity.
|
|
191 assert syncBits & hSync != 0
|
|
192
|
|
193 # VGA 640x480 defaults (to be adjusted below!)
|
|
194 vFront = 10 # Vertical front porch
|
|
195 vPulse = 2 # Vertical sync pulse
|
|
196 vBack = 33 # Vertical back porch
|
|
197 vgaLines = vFront + vPulse + vBack + 480
|
|
198 vgaClock = 25.175e+06
|
|
199
|
|
200 # Video adjustments for Gigatron
|
|
201 # 1. Our clock is (slightly) slower than 1/4th VGA clock. Not all monitors will
|
|
202 # accept the decreased frame rate, so we restore the frame rate to above
|
|
203 # minimum 59.94 Hz by cutting some lines from the vertical front porch.
|
|
204 vFrontAdjust = vgaLines - int(4 * cpuClock / vgaClock * vgaLines)
|
|
205 vFront -= vFrontAdjust
|
|
206 # 2. Extend vertical sync pulse so we can feed the game controller the same
|
|
207 # signal. This is needed for controllers based on the 4021 instead of 74165
|
|
208 vPulseExtension = max(0, 8-vPulse)
|
|
209 vPulse += vPulseExtension
|
|
210 # 3. Borrow these lines from the back porch so the refresh rate remains
|
|
211 # unaffected
|
|
212 vBack -= vPulseExtension
|
|
213
|
|
214 # Start value of vertical blank counter
|
|
215 videoYline0 = 1-2*(vFront+vPulse+vBack-2)
|
|
216
|
|
217 # Mismatch between video lines and sound channels
|
|
218 soundDiscontinuity = (vFront+vPulse+vBack) % 4
|
|
219
|
|
220 # QQVGA resolution
|
|
221 qqVgaWidth = 160
|
|
222 qqVgaHeight = 120
|
|
223
|
|
224 # Game controller bits (actual controllers in kit have negative output)
|
|
225 # +----------------------------------------+
|
|
226 # | Up B* |
|
|
227 # | Left Right B A* |
|
|
228 # | Down Select Start A |
|
|
229 # +----------------------------------------+ *=Auto fire
|
|
230 buttonRight = 1
|
|
231 buttonLeft = 2
|
|
232 buttonDown = 4
|
|
233 buttonUp = 8
|
|
234 buttonStart = 16
|
|
235 buttonSelect = 32
|
|
236 buttonB = 64
|
|
237 buttonA = 128
|
|
238
|
|
239 #-----------------------------------------------------------------------
|
|
240 #
|
|
241 # RAM page 0: zero-page variables
|
|
242 #
|
|
243 #-----------------------------------------------------------------------
|
|
244
|
|
245 # Memory size in pages from auto-detect
|
|
246 memSize = zpByte()
|
|
247
|
|
248 # The current channel number for sound generation. Advanced every scan line
|
|
249 # and independent of the vertical refresh to maintain constant oscillation.
|
|
250 channel = zpByte()
|
|
251
|
|
252 # Next sound sample being synthesized
|
|
253 sample = zpByte()
|
|
254 # To save one instruction in the critical inner loop, `sample' is always
|
|
255 # reset with its own address instead of, for example, the value 0. Compare:
|
|
256 # 1 instruction reset
|
|
257 # st sample,[sample]
|
|
258 # 2 instruction reset:
|
|
259 # ld 0
|
|
260 # st [sample]
|
|
261 # The difference is not audible. This is fine when the reset/address
|
|
262 # value is low and doesn't overflow with 4 channels added to it.
|
|
263 # There is an alternative, but it requires pull-down diodes on the data bus:
|
|
264 # st [sample],[sample]
|
|
265 assert 4*63 + sample < 256
|
|
266 # We pin this reset/address value to 3, so `sample' swings from 3 to 255
|
|
267 assert sample == 3
|
|
268
|
|
269 # Former bootCount and bootCheck (<= ROMv3)
|
|
270 zpReserved = zpByte() # Recycled and still unused. Candidate future uses:
|
|
271 # - Video driver high address (for alternative video modes)
|
|
272 # - v6502: ADH offset ("MMU")
|
|
273 # - v8080: ???
|
|
274 vCpuSelect = zpByte() # Active interpreter page
|
|
275
|
|
276 # Entropy harvested from SRAM startup and controller input
|
|
277 entropy = zpByte(3)
|
|
278
|
|
279 # Visible video
|
|
280 videoY = zpByte() # Counts up from 0 to 238 in steps of 2
|
|
281 # Counts up (and is odd) during vertical blank
|
|
282 videoModeB = zpByte() # Handler for every 2nd line (pixel burst or vCPU)
|
|
283 videoModeC = zpByte() # Handler for every 3rd line (pixel burst or vCPU)
|
|
284 videoModeD = zpByte() # Handler for every 4th line (pixel burst or vCPU)
|
|
285
|
|
286 nextVideo = zpByte() # Jump offset to scan line handler (videoA, B, C...)
|
|
287 videoPulse = nextVideo # Used for pulse width modulation
|
|
288
|
|
289 # Frame counter is good enough as system clock
|
|
290 frameCount = zpByte(1)
|
|
291
|
|
292 # Serial input (game controller)
|
|
293 serialRaw = zpByte() # New raw serial read
|
|
294 serialLast = zpByte() # Previous serial read
|
|
295 buttonState = zpByte() # Clearable button state
|
|
296 resetTimer = zpByte() # After 2 seconds of holding 'Start', do a soft reset
|
|
297 # XXX move to page 1 to free up space
|
|
298
|
|
299 # Extended output (blinkenlights in bit 0:3 and audio in bit 4:7). This
|
|
300 # value must be present in AC during a rising hSync edge. It then gets
|
|
301 # copied to the XOUT register by the hardware. The XOUT register is only
|
|
302 # accessible in this indirect manner because it isn't part of the core
|
|
303 # CPU architecture.
|
|
304 xout = zpByte()
|
|
305 xoutMask = zpByte() # The blinkenlights and sound on/off state
|
|
306
|
|
307 # vCPU interpreter
|
|
308 vTicks = zpByte() # Interpreter ticks are units of 2 clocks
|
|
309 vPC = zpByte(2) # Interpreter program counter, points into RAM
|
|
310 vAC = zpByte(2) # Interpreter accumulator, 16-bits
|
|
311 vLR = zpByte(2) # Return address, for returning after CALL
|
|
312 vSP = zpByte(1) # Stack pointer
|
|
313 vTmp = zpByte()
|
|
314 vReturn = zpByte() # Return into video loop (in page of vBlankStart)
|
|
315
|
|
316 # Scratch
|
|
317 frameX = zpByte() # Starting byte within page
|
|
318 frameY = zpByte() # Page of current pixel line (updated by videoA)
|
|
319
|
|
320 # Vertical blank (reuse some variables used in the visible part)
|
|
321 videoSync0 = frameX # Vertical sync type on current line (0xc0 or 0x40)
|
|
322 videoSync1 = frameY # Same during horizontal pulse (0x80 or 0x00)
|
|
323
|
|
324 # Versioning for GT1 compatibility
|
|
325 # Please refer to Docs/GT1-files.txt for interpreting this variable
|
|
326 romType = zpByte(1)
|
|
327
|
|
328 # The low 3 bits are repurposed to select the actively updated sound channels.
|
|
329 # Valid bit combinations are:
|
|
330 # xxxxx011 Default after reset: 4 channels (page 1,2,3,4)
|
|
331 # xxxxx001 2 channels at double update rate (page 1,2)
|
|
332 # xxxxx000 1 channel at quadruple update rate (page 1)
|
|
333 # The main application for this is to free up the high bytes of page 2,3,4.
|
|
334 channelMask = symbol('channelMask_v4')
|
|
335 assert romType == channelMask
|
|
336
|
|
337 # SYS function arguments and results/scratch
|
|
338 sysFn = zpByte(2)
|
|
339 sysArgs = zpByte(8)
|
|
340
|
|
341 # Play sound if non-zero, count down and stop sound when zero
|
|
342 soundTimer = zpByte()
|
|
343
|
|
344 # Fow now the LED state machine itself is hard-coded in the program ROM
|
|
345 ledTimer = zpByte() # Number of ticks until next LED change
|
|
346 ledState_v2 = zpByte() # Current LED state
|
|
347 ledTempo = zpByte() # Next value for ledTimer after LED state change
|
|
348
|
|
349 # All bytes above, except 0x80, are free for temporary/scratch/stacks etc
|
|
350 userVars = zpByte(0)
|
|
351
|
|
352 #-----------------------------------------------------------------------
|
|
353 #
|
|
354 # RAM page 1: video line table
|
|
355 #
|
|
356 #-----------------------------------------------------------------------
|
|
357
|
|
358 # Byte 0-239 define the video lines
|
|
359 videoTable = 0x0100 # Indirection table: Y[0] dX[0] ..., Y[119] dX[119]
|
|
360
|
|
361 vReset = 0x01f0
|
|
362 vIRQ_v5 = 0x01f6
|
|
363 ctrlBits = 0x01f8
|
|
364 videoTop_v5 = 0x01f9 # Number of skip lines
|
|
365
|
|
366 # Highest bytes are for sound channel variables
|
|
367 wavA = 250 # Waveform modulation with `adda'
|
|
368 wavX = 251 # Waveform modulation with `xora'
|
|
369 keyL = 252 # Frequency low 7 bits (bit7 == 0)
|
|
370 keyH = 253 # Frequency high 8 bits
|
|
371 oscL = 254 # Phase low 7 bits
|
|
372 oscH = 255 # Phase high 8 bits
|
|
373
|
|
374 #-----------------------------------------------------------------------
|
|
375 # Memory layout
|
|
376 #-----------------------------------------------------------------------
|
|
377
|
|
378 userCode = 0x0200 # Application vCPU code
|
|
379 soundTable = 0x0700 # Wave form tables (doubles as right-shift-2 table)
|
|
380 screenMemory = 0x0800 # Default start of screen memory: 0x0800 to 0x7fff
|
|
381
|
|
382 #-----------------------------------------------------------------------
|
|
383 # Application definitions
|
|
384 #-----------------------------------------------------------------------
|
|
385
|
|
386 maxTicks = 28//2 # Duration of vCPU's slowest virtual opcode (ticks)
|
|
387 minTicks = 14//2 # vcPU's fastest instruction
|
|
388 v6502_maxTicks = 38//2 # Max duration of v6502 processing phase (ticks)
|
|
389
|
|
390 runVcpu_overhead = 5 # Caller overhead (cycles)
|
|
391 vCPU_overhead = 9 # Callee overhead of jumping in and out (cycles)
|
|
392 v6502_overhead = 11 # Callee overhead for v6502 (cycles)
|
|
393
|
|
394 v6502_adjust = (v6502_maxTicks - maxTicks) + (v6502_overhead - vCPU_overhead)//2
|
|
395 assert v6502_adjust >= 0 # v6502's overhead is a bit more than vCPU
|
|
396
|
|
397 def runVcpu(n, ref=None, returnTo=None):
|
|
398 """Macro to run interpreter for exactly n cycles. Returns 0 in AC.
|
|
399
|
|
400 - `n' is the number of available Gigatron cycles including overhead.
|
|
401 This is converted into interpreter ticks and takes into account
|
|
402 the vCPU calling overheads. A `nop' is inserted when necessary
|
|
403 for alignment between cycles and ticks.
|
|
404 - `returnTo' is where program flow continues after return. If not set
|
|
405 explicitely, it will be the first instruction behind the expansion.
|
|
406 - If another interpreter than vCPU is active (v6502...), that one
|
|
407 must adjust for the timing differences, because runVcpu wouldn't know."""
|
|
408
|
|
409 overhead = runVcpu_overhead + vCPU_overhead
|
|
410 if returnTo == 0x100: # Special case for videoZ
|
|
411 overhead -= 2
|
|
412
|
|
413 if n is None:
|
|
414 # (Clumsily) create a maximum time slice, corresponding to a vTicks
|
|
415 # value of 127 (giving 282 cycles). A higher value doesn't work because
|
|
416 # then SYS functions that just need 28 cycles (0 excess) won't start.
|
|
417 n = (127 + maxTicks) * 2 + overhead
|
|
418
|
|
419 n -= overhead
|
|
420 assert n > 0
|
|
421
|
|
422 if n % 2 == 1:
|
|
423 nop() # Tick alignment
|
|
424 n -= 1
|
|
425 assert n % 2 == 0
|
|
426
|
|
427 print('runVcpu at $%04x net cycles %3s info %s' % (pc(), n, ref))
|
|
428
|
|
429 if returnTo != 0x100:
|
|
430 if returnTo is None:
|
|
431 returnTo = pc() + 5 # Next instruction
|
|
432 ld(lo(returnTo)) #0
|
|
433 st([vReturn]) #1
|
|
434
|
|
435 n //= 2
|
|
436 n -= maxTicks # First instruction always runs
|
|
437 assert n < 128
|
|
438 assert n >= v6502_adjust
|
|
439
|
|
440 ld([vCpuSelect],Y) #2
|
|
441 jmp(Y,'ENTER') #3
|
|
442 ld(n) #4
|
|
443 assert runVcpu_overhead == 5
|
|
444
|
|
445 #-----------------------------------------------------------------------
|
|
446 # v6502 definitions
|
|
447 #-----------------------------------------------------------------------
|
|
448
|
|
449 # Registers are zero page variables
|
|
450 v6502_PC = vLR # Program Counter
|
|
451 v6502_PCL = vLR+0 # Program Counter Low
|
|
452 v6502_PCH = vLR+1 # Program Counter High
|
|
453 v6502_S = vSP # Stack Pointer (kept as "S+1")
|
|
454 v6502_A = vAC+0 # Accumulator
|
|
455 v6502_BI = vAC+1 # B Input Register (used by SBC)
|
|
456 v6502_ADL = sysArgs+0 # Low Address Register
|
|
457 v6502_ADH = sysArgs+1 # High Address Register
|
|
458 v6502_IR = sysArgs+2 # Instruction Register
|
|
459 v6502_P = sysArgs+3 # Processor Status Register (V flag in bit 7)
|
|
460 v6502_Qz = sysArgs+4 # Quick Status Register for Z flag
|
|
461 v6502_Qn = sysArgs+5 # Quick Status Register for N flag
|
|
462 v6502_X = sysArgs+6 # Index Register X
|
|
463 v6502_Y = sysArgs+7 # Index Register Y
|
|
464 v6502_Tmp = vTmp # Scratch (may be clobbered outside v6502)
|
|
465
|
|
466 # MOS 6502 definitions for P register
|
|
467 v6502_Cflag = 1 # Carry Flag (unsigned overflow)
|
|
468 v6502_Zflag = 2 # Zero Flag (all bits zero)
|
|
469 v6502_Iflag = 4 # Interrupt Enable Flag (1=Disable)
|
|
470 v6502_Dflag = 8 # Decimal Enable Flag (aka BCD mode, 1=Enable)
|
|
471 v6502_Bflag = 16 # Break (or PHP) Instruction Flag
|
|
472 v6502_Uflag = 32 # Unused (always 1)
|
|
473 v6502_Vflag = 64 # Overflow Flag (signed overflow)
|
|
474 v6502_Nflag = 128 # Negative Flag (bit 7 of result)
|
|
475
|
|
476 # In emulation it is much faster to keep the V flag in bit 7
|
|
477 # This can be corrected when importing/exporting with PHP, PLP, etc
|
|
478 v6502_Vemu = 128
|
|
479
|
|
480 # On overflow:
|
|
481 # """Overflow is set if two inputs with the same sign produce
|
|
482 # a result with a different sign. Otherwise it is clear."""
|
|
483 # Formula (without carry/borrow in!):
|
|
484 # (A ^ (A+B)) & (B ^ (A+B)) & 0x80
|
|
485 # References:
|
|
486 # http://www.righto.com/2012/12/the-6502-overflow-flag-explained.html
|
|
487 # http://6502.org/tutorials/vflag.html
|
|
488
|
|
489 # Memory layout
|
|
490 v6502_Stack = 0x0000 # 0x0100 is already used in the Gigatron
|
|
491 #v6502_NMI = 0xfffa
|
|
492 #v6502_RESET = 0xfffc
|
|
493 #v6502_IRQ = 0xfffe
|
|
494
|
|
495 #-----------------------------------------------------------------------
|
|
496 #
|
|
497 # $0000 ROM page 0: Boot
|
|
498 #
|
|
499 #-----------------------------------------------------------------------
|
|
500
|
|
501 align(0x100, size=0x80)
|
|
502
|
|
503 # Give a first sign of life that can be checked with a voltmeter
|
|
address
|
|
| encoding
|
|
| | instruction
|
|
| | | operands
|
|
| | | |
|
|
V V V V
|
|
0000 0000 ld $00 504 ld(0b0000) # LEDs |OOOO|
|
|
0001 1880 ld $80,out 505 ld(syncBits^hSync,OUT) # Prepare XOUT update, hSync goes down, RGB to black
|
|
0002 18c0 ld $c0,out 506 ld(syncBits,OUT) # hSync goes up, updating XOUT
|
|
507
|
|
508 # Setup I/O and RAM expander
|
|
0003 c17c ctrl $7c 509 ctrl(0b01111100) # Disable SPI slaves, enable RAM, bank 1
|
|
510 # ^^^^^^^^
|
|
511 # |||||||`-- SCLK
|
|
512 # ||||||`--- Not connected
|
|
513 # |||||`---- /SS0
|
|
514 # ||||`----- /SS1
|
|
515 # |||`------ /SS2
|
|
516 # ||`------- /SS3
|
|
517 # |`-------- B0
|
|
518 # `--------- B1
|
|
519 # bit15 --------- MOSI = 0
|
|
520
|
|
521 # Simple RAM test and size check by writing to [1<<n] and see if [0] changes or not.
|
|
0004 0001 ld $01 522 ld(1) # Quick RAM test and count
|
|
523 label('.countMem0')
|
|
.countMem0: 0005 d601 st [$01],y 524 st([memSize],Y) # Store in RAM and load AC in Y
|
|
0006 00ff ld $ff 525 ld(255)
|
|
0007 6900 xora [y,$00] 526 xora([Y,0]) # Invert value from memory
|
|
0008 ca00 st [y,$00] 527 st([Y,0]) # Test RAM by writing the new value
|
|
0009 c200 st [$00] 528 st([0]) # Copy result in [0]
|
|
000a 6900 xora [y,$00] 529 xora([Y,0]) # Read back and compare if written ok
|
|
000b ec0b bne $000b 530 bne(pc()) # Loop forever on RAM failure here
|
|
000c 00ff ld $ff 531 ld(255)
|
|
000d 6900 xora [y,$00] 532 xora([Y,0]) # Invert memory value again
|
|
000e ca00 st [y,$00] 533 st([Y,0]) # To restore original value
|
|
000f 6100 xora [$00] 534 xora([0]) # Compare with inverted copy
|
|
0010 f014 beq .countMem1 535 beq('.countMem1') # If equal, we wrapped around
|
|
0011 0101 ld [$01] 536 ld([memSize])
|
|
0012 fc05 bra .countMem0 537 bra('.countMem0') # Loop to test next address line
|
|
0013 8200 adda ac 538 adda(AC) # Executes in the branch delay slot!
|
|
539 label('.countMem1')
|
|
540
|
|
541 # Momentarily wait to allow for debouncing of the reset switch by spinning
|
|
542 # roughly 2^15 times at 2 clocks per loop: 6.5ms@10MHz to 10ms@6.3MHz
|
|
543 # Real-world switches normally bounce shorter than that.
|
|
544 # "[...] 16 switches exhibited an average 1557 usec of bouncing, with,
|
|
545 # as I said, a max of 6200 usec" (From: http://www.ganssle.com/debouncing.htm)
|
|
546 # Relevant for the breadboard version, as the kit doesn't have a reset switch.
|
|
547
|
|
.countMem1: 0014 00ff ld $ff 548 ld(255) # Debounce reset button
|
|
549 label('.debounce')
|
|
.debounce: 0015 c200 st [$00] 550 st([0])
|
|
0016 ec16 bne $0016 551 bne(pc())
|
|
0017 a001 suba $01 552 suba(1) # Branch delay slot
|
|
0018 0100 ld [$00] 553 ld([0])
|
|
0019 ec15 bne .debounce 554 bne('.debounce')
|
|
001a a001 suba $01 555 suba(1) # Branch delay slot
|
|
556
|
|
557 # Update LEDs (memory is present and counted, reset is stable)
|
|
001b 0001 ld $01 558 ld(0b0001) # LEDs |*OOO|
|
|
001c 1880 ld $80,out 559 ld(syncBits^hSync,OUT)
|
|
001d 18c0 ld $c0,out 560 ld(syncBits,OUT)
|
|
561
|
|
562 # Scan the entire RAM space to collect entropy for a random number generator.
|
|
563 # The 16-bit address space is scanned, even if less RAM was detected.
|
|
001e 0000 ld $00 564 ld(0) # Collect entropy from RAM
|
|
001f d218 st [$18],x 565 st([vAC+0],X)
|
|
0020 d619 st [$19],y 566 st([vAC+1],Y)
|
|
567 label('.initEnt0')
|
|
.initEnt0: 0021 0106 ld [$06] 568 ld([entropy+0])
|
|
0022 f425 bge .initEnt1 569 bpl('.initEnt1')
|
|
0023 8d00 adda [y,x] 570 adda([Y,X])
|
|
0024 60bf xora $bf 571 xora(191)
|
|
572 label('.initEnt1')
|
|
.initEnt1: 0025 c206 st [$06] 573 st([entropy+0])
|
|
0026 0107 ld [$07] 574 ld([entropy+1])
|
|
0027 f42a bge .initEnt2 575 bpl('.initEnt2')
|
|
0028 8106 adda [$06] 576 adda([entropy+0])
|
|
0029 60c1 xora $c1 577 xora(193)
|
|
578 label('.initEnt2')
|
|
.initEnt2: 002a c207 st [$07] 579 st([entropy+1])
|
|
002b 8108 adda [$08] 580 adda([entropy+2])
|
|
002c c208 st [$08] 581 st([entropy+2])
|
|
002d 0118 ld [$18] 582 ld([vAC+0])
|
|
002e 8001 adda $01 583 adda(1)
|
|
002f ec21 bne .initEnt0 584 bne('.initEnt0')
|
|
0030 d218 st [$18],x 585 st([vAC+0],X)
|
|
0031 0119 ld [$19] 586 ld([vAC+1])
|
|
0032 8001 adda $01 587 adda(1)
|
|
0033 ec21 bne .initEnt0 588 bne('.initEnt0')
|
|
0034 d619 st [$19],y 589 st([vAC+1],Y)
|
|
590
|
|
591 # Update LEDs
|
|
0035 0003 ld $03 592 ld(0b0011) # LEDs |**OO|
|
|
0036 1880 ld $80,out 593 ld(syncBits^hSync,OUT)
|
|
0037 18c0 ld $c0,out 594 ld(syncBits,OUT)
|
|
595
|
|
596 # vCPU reset handler
|
|
0038 00ee ld $ee 597 ld((vReset&255)-2) # Setup vCPU reset handler
|
|
0039 c216 st [$16] 598 st([vPC])
|
|
003a 9002 adda $02,x 599 adda(2,X)
|
|
003b 0001 ld $01 600 ld(vReset>>8)
|
|
003c d617 st [$17],y 601 st([vPC+1],Y)
|
|
003d dc59 st $59,[y,x++] 602 st('LDI', [Y,Xpp])
|
|
003e dc5e st $5e,[y,x++] 603 st('SYS_Reset_88', [Y,Xpp])
|
|
003f dc2b st $2b,[y,x++] 604 st('STW', [Y,Xpp])
|
|
0040 dc22 st $22,[y,x++] 605 st(sysFn, [Y,Xpp])
|
|
0041 dcb4 st $b4,[y,x++] 606 st('SYS', [Y,Xpp]) # SYS -> SYS_Reset_88 -> SYS_Exec_88
|
|
0042 dce2 st $e2,[y,x++] 607 st(256-88//2+maxTicks,[Y,Xpp])
|
|
0043 dc00 st $00,[y,x++] 608 st(0, [Y,Xpp]) # vIRQ_v5: Disable interrupts
|
|
0044 dc00 st $00,[y,x++] 609 st(0, [Y,Xpp]) # vIRQ_v5
|
|
0045 dcfc st $fc,[y,x++] 610 st(0b11111100, [Y,Xpp]) # Control register
|
|
0046 dc00 st $00,[y,x++] 611 st(0, [Y,Xpp]) # videoTop
|
|
612
|
|
0047 0002 ld $02 613 ld(hi('ENTER')) # Active interpreter (vCPU,v6502) = vCPU
|
|
0048 c205 st [$05] 614 st([vCpuSelect])
|
|
615
|
|
0049 00ff ld $ff 616 ld(255) # Setup serial input
|
|
004a c20e st [$0e] 617 st([frameCount])
|
|
004b c20f st [$0f] 618 st([serialRaw])
|
|
004c c210 st [$10] 619 st([serialLast])
|
|
004d c211 st [$11] 620 st([buttonState])
|
|
004e c212 st [$12] 621 st([resetTimer]) # resetTimer<0 when entering Main.gcl
|
|
622
|
|
004f 0007 ld $07 623 ld(0b0111) # LEDs |***O|
|
|
0050 1880 ld $80,out 624 ld(syncBits^hSync,OUT)
|
|
0051 18c0 ld $c0,out 625 ld(syncBits,OUT)
|
|
626
|
|
0052 0000 ld $00 627 ld(0)
|
|
0053 c200 st [$00] 628 st([0]) # Carry lookup ([0x80] in 1st line of vBlank)
|
|
0054 c202 st [$02] 629 st([channel])
|
|
0055 c22c st [$2c] 630 st([soundTimer])
|
|
631
|
|
0056 000f ld $0f 632 ld(0b1111) # LEDs |****|
|
|
0057 1880 ld $80,out 633 ld(syncBits^hSync,OUT)
|
|
0058 18c0 ld $c0,out 634 ld(syncBits,OUT)
|
|
0059 c213 st [$13] 635 st([xout]) # Setup for control by video loop
|
|
005a c214 st [$14] 636 st([xoutMask])
|
|
637
|
|
005b 1401 ld $01,y 638 ld(hi('startVideo'),Y) # Enter video loop at vertical blank
|
|
005c e003 jmp y,$03 639 jmp(Y,'startVideo')
|
|
005d c22e st [$2e] 640 st([ledState_v2]) # Setting to 1..126 means "stopped"
|
|
641
|
|
642 #-----------------------------------------------------------------------
|
|
643 # Extension SYS_Reset_88: Soft reset
|
|
644 #-----------------------------------------------------------------------
|
|
645
|
|
646 # SYS_Reset_88 initiates an immediate Gigatron reset from within the vCPU.
|
|
647 # The reset sequence itself is mostly implemented in GCL by Reset.gcl,
|
|
648 # which must first be loaded into RAM. But as that takes more than 1 scanline,
|
|
649 # some vCPU bootstrapping code gets loaded with SYS_Exec_88.
|
|
650 # !!! This function was REMOVED from interface.json
|
|
651 # !!! Better use vReset as generic entry point for soft reset
|
|
652
|
|
653 # ROM type (see also Docs/GT1-files.txt)
|
|
654 romTypeValue = symbol('romTypeValue_ROMv5')
|
|
655
|
|
656 label('SYS_Reset_88')
|
|
657 assert pc()>>8 == 0
|
|
658 assert (romTypeValue & 7) == 0
|
|
SYS_Reset_88: 005e 0040 ld $40 659 ld(romTypeValue) #15 Set ROM type/version and clear channel mask
|
|
005f c221 st [$21] 660 st([romType]) #16
|
|
0060 0000 ld $00 661 ld(0) #17
|
|
0061 c21c st [$1c] 662 st([vSP]) #18 vSP
|
|
0062 1401 ld $01,y 663 ld(hi('videoTop_v5'),Y) #19
|
|
0063 caf9 st [y,$f9] 664 st([Y,lo('videoTop_v5')]) #20 Show all 120 pixel lines
|
|
0064 caf6 st [y,$f6] 665 st([Y,vIRQ_v5]) #21 Disable vIRQ dispatch
|
|
0065 caf7 st [y,$f7] 666 st([Y,vIRQ_v5+1]) #22
|
|
0066 c22c st [$2c] 667 st([soundTimer]) #23 soundTimer
|
|
668 assert userCode&255 == 0
|
|
0067 c21a st [$1a] 669 st([vLR]) #24 vLR
|
|
0068 0002 ld $02 670 ld(userCode>>8) #25
|
|
0069 c21b st [$1b] 671 st([vLR+1]) #26
|
|
006a 00f6 ld $f6 672 ld('nopixels') #27 Video mode 3 (fast)
|
|
006b c20a st [$0a] 673 st([videoModeB]) #28
|
|
006c c20b st [$0b] 674 st([videoModeC]) #29
|
|
006d c20c st [$0c] 675 st([videoModeD]) #30
|
|
006e 00ad ld $ad 676 ld('SYS_Exec_88') #31 SYS_Exec_88
|
|
006f c222 st [$22] 677 st([sysFn]) #32 High byte (remains) 0
|
|
0070 0000 ld $00 678 ld('Reset') #33 Reset.gt1 from EPROM
|
|
0071 c224 st [$24] 679 st([sysArgs+0]) #34
|
|
0072 0000 ld $00 680 ld(hi('Reset')) #35
|
|
0073 c225 st [$25] 681 st([sysArgs+1]) #36
|
|
0074 0116 ld [$16] 682 ld([vPC]) #37 Force second SYS call
|
|
0075 a002 suba $02 683 suba(2) #38
|
|
0076 c216 st [$16] 684 st([vPC]) #39
|
|
685 # Return to interpreter
|
|
0077 1403 ld $03,y 686 ld(hi('NEXTY'),Y) #40
|
|
0078 e000 jmp y,$00 687 jmp(Y,'NEXTY') #41
|
|
0079 00ea ld $ea 688 ld(-44/2) #42
|
|
689
|
|
690 #-----------------------------------------------------------------------
|
|
691 # Placeholders for future SYS functions. This works as a kind of jump
|
|
692 # table. The indirection allows SYS implementations to be moved around
|
|
693 # between ROM versions, at the expense of 2 clock cycles (or 1). When
|
|
694 # the function is not present it just acts as a NOP. Of course, when a
|
|
695 # SYS function must be patched or extended it needs to have budget for
|
|
696 # that in its declared maximum cycle count.
|
|
697 #
|
|
698 # Technically the same goal can be achieved by starting each function
|
|
699 # with 2 nop's, or by overdeclaring their duration in the first place
|
|
700 # (a bit is still wise to do). But this can result in fragmentation
|
|
701 # of future ROM images. The indirection avoids that.
|
|
702 #
|
|
703 # An added advantage of having these in ROM page 0 is that it saves one
|
|
704 # byte when setting sysFn: LDI+STW (4 bytes) instead of LDWI+STW (5 bytes)
|
|
705 #-----------------------------------------------------------------------
|
|
706
|
|
007a 0200 nop 707 align(0x80, size=0x80)
|
|
007b 0200 nop
|
|
007c 0200 nop
|
|
* 6 times
|
|
708 assert pc() == 0x80
|
|
709
|
|
0080 1403 ld $03,y 710 ld(hi('REENTER'),Y) #15 slot 0x80
|
|
0081 e0cb jmp y,$cb 711 jmp(Y,'REENTER') #16
|
|
0082 00f6 ld $f6 712 ld(-20/2) #17
|
|
713
|
|
0083 1403 ld $03,y 714 ld(hi('REENTER'),Y) #15 slot 0x83
|
|
0084 e0cb jmp y,$cb 715 jmp(Y,'REENTER') #16
|
|
0085 00f6 ld $f6 716 ld(-20/2) #17
|
|
717
|
|
0086 1403 ld $03,y 718 ld(hi('REENTER'),Y) #15 slot 0x86
|
|
0087 e0cb jmp y,$cb 719 jmp(Y,'REENTER') #16
|
|
0088 00f6 ld $f6 720 ld(-20/2) #17
|
|
721
|
|
0089 1403 ld $03,y 722 ld(hi('REENTER'),Y) #15 slot 0x89
|
|
008a e0cb jmp y,$cb 723 jmp(Y,'REENTER') #16
|
|
008b 00f6 ld $f6 724 ld(-20/2) #17
|
|
725
|
|
008c 1403 ld $03,y 726 ld(hi('REENTER'),Y) #15 slot 0x8c
|
|
008d e0cb jmp y,$cb 727 jmp(Y,'REENTER') #16
|
|
008e 00f6 ld $f6 728 ld(-20/2) #17
|
|
729
|
|
008f 1403 ld $03,y 730 ld(hi('REENTER'),Y) #15 slot 0x8f
|
|
0090 e0cb jmp y,$cb 731 jmp(Y,'REENTER') #16
|
|
0091 00f6 ld $f6 732 ld(-20/2) #17
|
|
733
|
|
0092 1403 ld $03,y 734 ld(hi('REENTER'),Y) #15 slot 0x92
|
|
0093 e0cb jmp y,$cb 735 jmp(Y,'REENTER') #16
|
|
0094 00f6 ld $f6 736 ld(-20/2) #17
|
|
737
|
|
0095 1403 ld $03,y 738 ld(hi('REENTER'),Y) #15 slot 0x95
|
|
0096 e0cb jmp y,$cb 739 jmp(Y,'REENTER') #16
|
|
0097 00f6 ld $f6 740 ld(-20/2) #17
|
|
741
|
|
0098 1403 ld $03,y 742 ld(hi('REENTER'),Y) #15 slot 0x98
|
|
0099 e0cb jmp y,$cb 743 jmp(Y,'REENTER') #16
|
|
009a 00f6 ld $f6 744 ld(-20/2) #17
|
|
745
|
|
009b 1403 ld $03,y 746 ld(hi('REENTER'),Y) #15 slot 0x9b
|
|
009c e0cb jmp y,$cb 747 jmp(Y,'REENTER') #16
|
|
009d 00f6 ld $f6 748 ld(-20/2) #17
|
|
749
|
|
009e 1403 ld $03,y 750 ld(hi('REENTER'),Y) #15 slot 0x9e
|
|
009f e0cb jmp y,$cb 751 jmp(Y,'REENTER') #16
|
|
00a0 00f6 ld $f6 752 ld(-20/2) #17
|
|
753
|
|
00a1 1403 ld $03,y 754 ld(hi('REENTER'),Y) #15 slot 0xa1
|
|
00a2 e0cb jmp y,$cb 755 jmp(Y,'REENTER') #16
|
|
00a3 00f6 ld $f6 756 ld(-20/2) #17
|
|
757
|
|
00a4 1403 ld $03,y 758 ld(hi('REENTER'),Y) #15 slot 0xa4
|
|
00a5 e0cb jmp y,$cb 759 jmp(Y,'REENTER') #16
|
|
00a6 00f6 ld $f6 760 ld(-20/2) #17
|
|
761
|
|
00a7 1403 ld $03,y 762 ld(hi('REENTER'),Y) #15 slot 0xa7
|
|
00a8 e0cb jmp y,$cb 763 jmp(Y,'REENTER') #16
|
|
00a9 00f6 ld $f6 764 ld(-20/2) #17
|
|
765
|
|
00aa 1403 ld $03,y 766 ld(hi('REENTER'),Y) #15 slot 0xaa
|
|
00ab e0cb jmp y,$cb 767 jmp(Y,'REENTER') #16
|
|
00ac 00f6 ld $f6 768 ld(-20/2) #17
|
|
769
|
|
770 #-----------------------------------------------------------------------
|
|
771 # Extension SYS_Exec_88: Load code from ROM into memory and execute it
|
|
772 #-----------------------------------------------------------------------
|
|
773 #
|
|
774 # This loads the vCPU code with consideration of the current vSP
|
|
775 # Used during reset, but also for switching between applications or for
|
|
776 # loading data from ROM from within an application (overlays).
|
|
777 #
|
|
778 # ROM stream format is [<addrH> <addrL> <n&255> n*<byte>]* 0
|
|
779 # on top of lookup tables.
|
|
780 #
|
|
781 # Variables:
|
|
782 # sysArgs[0:1] ROM pointer (in)
|
|
783 # sysArgs[2:3] RAM pointer (changed)
|
|
784 # sysArgs[4] State counter (changed)
|
|
785 # vLR vCPU continues here (in)
|
|
786
|
|
787 label('SYS_Exec_88')
|
|
SYS_Exec_88: 00ad 1412 ld $12,y 788 ld(hi('sys_Exec'),Y) #15
|
|
00ae e04b jmp y,$4b 789 jmp(Y,'sys_Exec') #16
|
|
00af 0000 ld $00 790 ld(0) #17 Address of loader on zero page
|
|
791
|
|
792 #-----------------------------------------------------------------------
|
|
793 # More placeholders for future SYS functions
|
|
794 #-----------------------------------------------------------------------
|
|
795
|
|
00b0 1403 ld $03,y 796 ld(hi('REENTER'),Y) #15 slot 0xb0
|
|
00b1 e0cb jmp y,$cb 797 jmp(Y,'REENTER') #16
|
|
00b2 00f6 ld $f6 798 ld(-20/2) #17
|
|
799
|
|
00b3 1403 ld $03,y 800 ld(hi('REENTER'),Y) #15 slot 0xb3
|
|
00b4 e0cb jmp y,$cb 801 jmp(Y,'REENTER') #16
|
|
00b5 00f6 ld $f6 802 ld(-20/2) #17
|
|
803
|
|
00b6 1403 ld $03,y 804 ld(hi('REENTER'),Y) #15 slot 0xb6
|
|
00b7 e0cb jmp y,$cb 805 jmp(Y,'REENTER') #16
|
|
00b8 00f6 ld $f6 806 ld(-20/2) #17
|
|
807
|
|
00b9 1403 ld $03,y 808 ld(hi('REENTER'),Y) #15 slot 0xb9
|
|
00ba e0cb jmp y,$cb 809 jmp(Y,'REENTER') #16
|
|
00bb 00f6 ld $f6 810 ld(-20/2) #17
|
|
811
|
|
00bc 1403 ld $03,y 812 ld(hi('REENTER'),Y) #15 slot 0xbc
|
|
00bd e0cb jmp y,$cb 813 jmp(Y,'REENTER') #16
|
|
00be 00f6 ld $f6 814 ld(-20/2) #17
|
|
815
|
|
00bf 1403 ld $03,y 816 ld(hi('REENTER'),Y) #15 slot 0xbf
|
|
00c0 e0cb jmp y,$cb 817 jmp(Y,'REENTER') #16
|
|
00c1 00f6 ld $f6 818 ld(-20/2) #17
|
|
819
|
|
00c2 1403 ld $03,y 820 ld(hi('REENTER'),Y) #15 slot 0xc2
|
|
00c3 e0cb jmp y,$cb 821 jmp(Y,'REENTER') #16
|
|
00c4 00f6 ld $f6 822 ld(-20/2) #17
|
|
823
|
|
00c5 1403 ld $03,y 824 ld(hi('REENTER'),Y) #15 slot 0xc5
|
|
00c6 e0cb jmp y,$cb 825 jmp(Y,'REENTER') #16
|
|
00c7 00f6 ld $f6 826 ld(-20/2) #17
|
|
827
|
|
00c8 1403 ld $03,y 828 ld(hi('REENTER'),Y) #15 slot 0xc8
|
|
00c9 e0cb jmp y,$cb 829 jmp(Y,'REENTER') #16
|
|
00ca 00f6 ld $f6 830 ld(-20/2) #17
|
|
831
|
|
00cb 1403 ld $03,y 832 ld(hi('REENTER'),Y) #15 slot 0xcb
|
|
00cc e0cb jmp y,$cb 833 jmp(Y,'REENTER') #16
|
|
00cd 00f6 ld $f6 834 ld(-20/2) #17
|
|
835
|
|
00ce 1403 ld $03,y 836 ld(hi('REENTER'),Y) #15 slot 0xce
|
|
00cf e0cb jmp y,$cb 837 jmp(Y,'REENTER') #16
|
|
00d0 00f6 ld $f6 838 ld(-20/2) #17
|
|
839
|
|
00d1 1403 ld $03,y 840 ld(hi('REENTER'),Y) #15 slot 0xd1
|
|
00d2 e0cb jmp y,$cb 841 jmp(Y,'REENTER') #16
|
|
00d3 00f6 ld $f6 842 ld(-20/2) #17
|
|
843
|
|
00d4 1403 ld $03,y 844 ld(hi('REENTER'),Y) #15 slot 0xd4
|
|
00d5 e0cb jmp y,$cb 845 jmp(Y,'REENTER') #16
|
|
00d6 00f6 ld $f6 846 ld(-20/2) #17
|
|
847
|
|
00d7 1403 ld $03,y 848 ld(hi('REENTER'),Y) #15 slot 0xd7
|
|
00d8 e0cb jmp y,$cb 849 jmp(Y,'REENTER') #16
|
|
00d9 00f6 ld $f6 850 ld(-20/2) #17
|
|
851
|
|
00da 1403 ld $03,y 852 ld(hi('REENTER'),Y) #15 slot 0xda
|
|
00db e0cb jmp y,$cb 853 jmp(Y,'REENTER') #16
|
|
00dc 00f6 ld $f6 854 ld(-20/2) #17
|
|
855
|
|
00dd 1403 ld $03,y 856 ld(hi('REENTER'),Y) #15 slot 0xdd
|
|
00de e0cb jmp y,$cb 857 jmp(Y,'REENTER') #16
|
|
00df 00f6 ld $f6 858 ld(-20/2) #17
|
|
859
|
|
00e0 1403 ld $03,y 860 ld(hi('REENTER'),Y) #15 slot 0xe0
|
|
00e1 e0cb jmp y,$cb 861 jmp(Y,'REENTER') #16
|
|
00e2 00f6 ld $f6 862 ld(-20/2) #17
|
|
863
|
|
00e3 1403 ld $03,y 864 ld(hi('REENTER'),Y) #15 slot 0xe3
|
|
00e4 e0cb jmp y,$cb 865 jmp(Y,'REENTER') #16
|
|
00e5 00f6 ld $f6 866 ld(-20/2) #17
|
|
867
|
|
00e6 1403 ld $03,y 868 ld(hi('REENTER'),Y) #15 slot 0xe6
|
|
00e7 e0cb jmp y,$cb 869 jmp(Y,'REENTER') #16
|
|
00e8 00f6 ld $f6 870 ld(-20/2) #17
|
|
871
|
|
872 #-----------------------------------------------------------------------
|
|
873 # Extension SYS_StoreBytes_DEVROM_XXX
|
|
874 #-----------------------------------------------------------------------
|
|
875
|
|
00e9 1403 ld $03,y 876 ld(hi('REENTER'),Y) #15 slot 0xe9
|
|
00ea e0cb jmp y,$cb 877 jmp(Y,'REENTER') #16
|
|
00eb 00f6 ld $f6 878 ld(-20/2) #17
|
|
879
|
|
880 #-----------------------------------------------------------------------
|
|
881 # Extension SYS_LoadBytes_DEVROM_XXX
|
|
882 #-----------------------------------------------------------------------
|
|
883
|
|
884 # Load object variables into zero-page
|
|
885 # XXX Unfinished
|
|
886 #
|
|
887 # Variables
|
|
888 # vLR Pointer to size byte + object variables
|
|
889 # $30...$30+n-1 Target location
|
|
890
|
|
891 label('SYS_LoadBytes_DEVROM_XXX')
|
|
SYS_LoadBytes_DEVROM_XXX:
|
|
00ec 1412 ld $12,y 892 ld(hi('sys_LoadBytes'),Y) #15
|
|
00ed e0e9 jmp y,$e9 893 jmp(Y,'sys_LoadBytes') #16
|
|
00ee 151b ld [$1b],y 894 ld([vLR+1],Y) #17
|
|
895
|
|
896 #-----------------------------------------------------------------------
|
|
897 # Extension SYS_ReadRomDir_v5_80
|
|
898 #-----------------------------------------------------------------------
|
|
899
|
|
900 # Get next entry from ROM file system. Use vAC=0 to get the first entry.
|
|
901
|
|
902 # Variables:
|
|
903 # vAC Start address of current entry (inout)
|
|
904 # sysArgs[0:7] File name, padded with zeroes (out)
|
|
905
|
|
906 label('SYS_ReadRomDir_v5_80')
|
|
SYS_ReadRomDir_v5_80:
|
|
00ef 1415 ld $15,y 907 ld(hi('sys_ReadRomDir'),Y) #15
|
|
00f0 e06f jmp y,$6f 908 jmp(Y,'sys_ReadRomDir') #16
|
|
00f1 0119 ld [$19] 909 ld([vAC+1]) #17
|
|
910
|
|
00f2 0200 nop 911 fillers(until=symbol('SYS_Out_22') & 255)
|
|
00f3 0200 nop
|
|
912
|
|
913 #-----------------------------------------------------------------------
|
|
914 # Extension SYS_Out_22
|
|
915 #-----------------------------------------------------------------------
|
|
916
|
|
917 # Send byte to output port
|
|
918 #
|
|
919 # Variables:
|
|
920 # vAC
|
|
921
|
|
922 label('SYS_Out_22')
|
|
SYS_Out_22: 00f4 1924 ld [$24],out 923 ld([sysArgs+0],OUT) #15
|
|
00f5 0200 nop 924 nop() #16
|
|
00f6 1403 ld $03,y 925 ld(hi('REENTER'),Y) #17
|
|
00f7 e0cb jmp y,$cb 926 jmp(Y,'REENTER') #18
|
|
00f8 00f5 ld $f5 927 ld(-22/2) #19
|
|
928
|
|
929 #-----------------------------------------------------------------------
|
|
930 # Extension SYS_In_24
|
|
931 #-----------------------------------------------------------------------
|
|
932
|
|
933 # Read a byte from the input port
|
|
934 #
|
|
935 # Variables:
|
|
936 # vAC
|
|
937
|
|
938 label('SYS_In_24')
|
|
SYS_In_24: 00f9 c318 st in,[$18] 939 st(IN, [vAC]) #15
|
|
00fa 0000 ld $00 940 ld(0) #16
|
|
00fb c219 st [$19] 941 st([vAC+1]) #17
|
|
00fc 0200 nop 942 nop() #18
|
|
00fd 1403 ld $03,y 943 ld(hi('REENTER'),Y) #19
|
|
00fe e0cb jmp y,$cb 944 jmp(Y,'REENTER') #20
|
|
00ff 00f4 ld $f4 945 ld(-24/2) #21
|
|
946
|
|
947 assert pc()&255 == 0
|
|
948
|
|
949 #-----------------------------------------------------------------------
|
|
950 #
|
|
951 # $0100 ROM page 1: Video loop vertical blank
|
|
952 #
|
|
953 #-----------------------------------------------------------------------
|
|
954 align(0x100, size=0x100)
|
|
955
|
|
956 # Video off mode (also no sound, serial, timer, blinkenlights, ...).
|
|
957 # For benchmarking purposes. This still has the overhead for the vTicks
|
|
958 # administration, time slice granularity etc.
|
|
959 label('videoZ')
|
|
960 videoZ = pc()
|
|
videoZ: 0100 1505 ld [$05],y 961 runVcpu(None, '---- novideo', returnTo=videoZ)
|
|
0101 e0ff jmp y,$ff
|
|
0102 007f ld $7f
|
|
962
|
|
963 label('startVideo') # (Re)start of video signal from idle state
|
|
startVideo: 0103 00c0 ld $c0 964 ld(syncBits)
|
|
965
|
|
966 # Start of vertical blank interval
|
|
967 label('vBlankStart')
|
|
vBlankStart: 0104 c21f st [$1f] 968 st([videoSync0]) #32 Start of vertical blank interval
|
|
0105 0080 ld $80 969 ld(syncBits^hSync) #33
|
|
0106 c220 st [$20] 970 st([videoSync1]) #34
|
|
971
|
|
972 # Reset line counter before vCPU can see it
|
|
0107 00b3 ld $b3 973 ld(videoYline0) #35
|
|
0108 c209 st [$09] 974 st([videoY]) #36
|
|
975
|
|
976 # Update frame count and [0x80] (4 cycles)
|
|
0109 0001 ld $01 977 ld(1) #37 Reinitialize carry lookup, for robustness
|
|
010a c280 st [$80] 978 st([0x80]) #38
|
|
010b 810e adda [$0e] 979 adda([frameCount]) #39 Frame counter
|
|
010c c20e st [$0e] 980 st([frameCount]) #40
|
|
981
|
|
982 # Mix entropy (11 cycles)
|
|
010d 6107 xora [$07] 983 xora([entropy+1]) #41 Mix entropy
|
|
010e 610f xora [$0f] 984 xora([serialRaw]) #42 Mix in serial input
|
|
010f 8106 adda [$06] 985 adda([entropy+0]) #43
|
|
0110 c206 st [$06] 986 st([entropy+0]) #44
|
|
0111 8108 adda [$08] 987 adda([entropy+2]) #45 Some hidden state
|
|
0112 c208 st [$08] 988 st([entropy+2]) #46
|
|
0113 e816 blt $0116 989 bmi(pc()+3) #47
|
|
0114 fc17 bra $0117 990 bra(pc()+3) #48
|
|
0115 6053 xora $53 991 xora(64+16+2+1) #49
|
|
0116 606c xora $6c 992 xora(64+32+8+4) #49(!)
|
|
0117 8107 adda [$07] 993 adda([entropy+1]) #50
|
|
0118 c207 st [$07] 994 st([entropy+1]) #51
|
|
995
|
|
996 # LED sequencer (18 cycles)
|
|
0119 012d ld [$2d] 997 ld([ledTimer]) #52 Blinkenlight sequencer
|
|
011a f01d beq $011d 998 beq(pc()+3) #53
|
|
011b fc1e bra $011e 999 bra(pc()+3) #54
|
|
011c a001 suba $01 1000 suba(1) #55
|
|
011d 012f ld [$2f] 1001 ld([ledTempo]) #55(!)
|
|
011e c22d st [$2d] 1002 st([ledTimer]) #56
|
|
011f f022 beq $0122 1003 beq(pc()+3) #57
|
|
0120 fc23 bra $0123 1004 bra(pc()+3) #58
|
|
0121 0000 ld $00 1005 ld(0) #59 Don't advance state
|
|
0122 0001 ld $01 1006 ld(1) #59(!) Advance state when timer passes through 0
|
|
0123 812e adda [$2e] 1007 adda([ledState_v2]) #60
|
|
0124 ec27 bne $0127 1008 bne(pc()+3) #61
|
|
0125 fc28 bra $0128 1009 bra(pc()+3) #62
|
|
0126 00e8 ld $e8 1010 ld(-24) #63 State 0 becomes -24, start of sequence
|
|
0127 e42c bgt .leds#65 1011 bgt('.leds#65') #63(!) Catch the stopped state (>0)
|
|
0128 c22e st [$2e] 1012 st([ledState_v2]) #64
|
|
0129 8048 adda $48 1013 adda('.leds#69') #65
|
|
012a fe00 bra ac 1014 bra(AC) #66 Jump to lookup table
|
|
012b fc48 bra .leds#69 1015 bra('.leds#69') #67 Single-instruction subroutine
|
|
1016
|
|
1017 label('.leds#65')
|
|
.leds#65: 012c 000f ld $0f 1018 ld(0x0f) #65 Maintain stopped state
|
|
012d c22e st [$2e] 1019 st([ledState_v2]) #66
|
|
012e fc48 bra .leds#69 1020 bra('.leds#69') #67
|
|
012f 2114 anda [$14] 1021 anda([xoutMask]) #68 Always clear sound bits (this is why AC=0x0f)
|
|
1022
|
|
0130 000f ld $0f 1023 ld(0b1111) #68 LEDs |****| offset -24 Low 4 bits are the LED output
|
|
0131 0007 ld $07 1024 ld(0b0111) #68 LEDs |***O|
|
|
0132 0003 ld $03 1025 ld(0b0011) #68 LEDs |**OO|
|
|
0133 0001 ld $01 1026 ld(0b0001) #68 LEDs |*OOO|
|
|
0134 0002 ld $02 1027 ld(0b0010) #68 LEDs |O*OO|
|
|
0135 0004 ld $04 1028 ld(0b0100) #68 LEDs |OO*O|
|
|
0136 0008 ld $08 1029 ld(0b1000) #68 LEDs |OOO*|
|
|
0137 0004 ld $04 1030 ld(0b0100) #68 LEDs |OO*O|
|
|
0138 0002 ld $02 1031 ld(0b0010) #68 LEDs |O*OO|
|
|
0139 0001 ld $01 1032 ld(0b0001) #68 LEDs |*OOO|
|
|
013a 0003 ld $03 1033 ld(0b0011) #68 LEDs |**OO|
|
|
013b 0007 ld $07 1034 ld(0b0111) #68 LEDs |***O|
|
|
013c 000f ld $0f 1035 ld(0b1111) #68 LEDs |****|
|
|
013d 000e ld $0e 1036 ld(0b1110) #68 LEDs |O***|
|
|
013e 000c ld $0c 1037 ld(0b1100) #68 LEDs |OO**|
|
|
013f 0008 ld $08 1038 ld(0b1000) #68 LEDs |OOO*|
|
|
0140 0004 ld $04 1039 ld(0b0100) #68 LEDs |OO*O|
|
|
0141 0002 ld $02 1040 ld(0b0010) #68 LEDs |O*OO|
|
|
0142 0001 ld $01 1041 ld(0b0001) #68 LEDs |*OOO|
|
|
0143 0002 ld $02 1042 ld(0b0010) #68 LEDs |O*OO|
|
|
0144 0004 ld $04 1043 ld(0b0100) #68 LEDs |OO*O|
|
|
0145 0008 ld $08 1044 ld(0b1000) #68 LEDs |OOO*|
|
|
0146 000c ld $0c 1045 ld(0b1100) #68 LEDs |OO**|
|
|
0147 000e ld $0e 1046 ld(0b1110) #68 LEDs |O***| offset -1
|
|
1047 label('.leds#69')
|
|
.leds#69: 0148 c214 st [$14] 1048 st([xoutMask]) #69 Sound bits will be re-enabled below
|
|
0149 0010 ld $10 1049 ld(vPulse*2) #70 vPulse default length when not modulated
|
|
014a c20d st [$0d] 1050 st([videoPulse]) #71
|
|
1051
|
|
1052 # When the total number of scan lines per frame is not an exact multiple of the
|
|
1053 # (4) channels, there will be an audible discontinuity if no measure is taken.
|
|
1054 # This static noise can be suppressed by swallowing the first `lines mod 4'
|
|
1055 # partial samples after transitioning into vertical blank. This is easiest if
|
|
1056 # the modulo is 0 (do nothing), 1 (reset sample when entering the last visible
|
|
1057 # scan line), or 2 (reset sample while in the first blank scan line). For the
|
|
1058 # last case there is no solution yet: give a warning.
|
|
1059 extra = 0
|
|
1060 if soundDiscontinuity == 2:
|
|
1061 st(sample, [sample]) # Sound continuity
|
|
1062 extra += 1
|
|
1063 if soundDiscontinuity > 2:
|
|
1064 highlight('Warning: sound discontinuity not suppressed')
|
|
1065
|
|
1066 # vCPU interrupt
|
|
014b 010e ld [$0e] 1067 ld([frameCount]) #72
|
|
1068 beq('vBlankFirst#75') #73
|
|
014c f052 beq vBlankFirst#75
|
|
1069
|
|
014d 0055 ld $55 1070 runVcpu(186-74-extra, #74 Application cycles (scan line 0)
|
|
014e c21e st [$1e]
|
|
014f 1505 ld [$05],y
|
|
0150 e0ff jmp y,$ff
|
|
0151 0023 ld $23
|
|
1071 '---D line 0 no timeout',
|
|
1072 returnTo='vBlankFirst#186')
|
|
1073
|
|
1074 label('vBlankFirst#75')
|
|
vBlankFirst#75:
|
|
0152 1412 ld $12,y 1075 ld(hi('vBlankFirst#78'),Y) #75
|
|
0153 e000 jmp y,$00 1076 jmp(Y,'vBlankFirst#78') #76
|
|
0154 1401 ld $01,y 1077 ld(hi(vIRQ_v5),Y) #77
|
|
1078 label('vBlankFirst#186')
|
|
1079
|
|
1080 # Mitigation for rogue channelMask (3 cycles)
|
|
vBlankFirst#186:
|
|
0155 0121 ld [$21] 1081 ld([channelMask]) #186 Normalize channelMask, for robustness
|
|
0156 20fb anda $fb 1082 anda(0b11111011) #187
|
|
0157 c221 st [$21] 1083 st([channelMask]) #188
|
|
1084
|
|
1085 # Sound on/off (6 cycles)
|
|
0158 012c ld [$2c] 1086 ld([soundTimer]) #189 Sound on/off
|
|
0159 ec5c bne $015c 1087 bne(pc()+3) #190
|
|
015a fc5d bra $015d 1088 bra(pc()+3) #191
|
|
015b 0000 ld $00 1089 ld(0) #192 Keeps sound unchanged (should be off here)
|
|
015c 00f0 ld $f0 1090 ld(0xf0) #192(!) Turns sound back on
|
|
015d 4114 ora [$14] 1091 ora([xoutMask]) #193
|
|
015e c214 st [$14] 1092 st([xoutMask]) #194
|
|
1093
|
|
1094 # Sound timer count down (5 cycles)
|
|
015f 012c ld [$2c] 1095 ld([soundTimer]) #195 Sound timer
|
|
0160 f063 beq $0163 1096 beq(pc()+3) #196
|
|
0161 fc64 bra $0164 1097 bra(pc()+3) #197
|
|
0162 a001 suba $01 1098 suba(1) #198
|
|
0163 0000 ld $00 1099 ld(0) #198
|
|
0164 c22c st [$2c] 1100 st([soundTimer]) #199
|
|
1101
|
|
0165 191f ld [$1f],out 1102 ld([videoSync0],OUT) #0 <New scan line start>
|
|
1103 label('sound1')
|
|
sound1: 0166 0102 ld [$02] 1104 ld([channel]) #1 Advance to next sound channel
|
|
0167 2121 anda [$21] 1105 anda([channelMask]) #2
|
|
0168 8001 adda $01 1106 adda(1) #3
|
|
0169 1920 ld [$20],out 1107 ld([videoSync1],OUT) #4 Start horizontal pulse
|
|
016a d602 st [$02],y 1108 st([channel],Y) #5
|
|
016b 007f ld $7f 1109 ld(0x7f) #6 Update sound channel
|
|
016c 29fe anda [y,$fe] 1110 anda([Y,oscL]) #7
|
|
016d 89fc adda [y,$fc] 1111 adda([Y,keyL]) #8
|
|
016e cafe st [y,$fe] 1112 st([Y,oscL]) #9
|
|
016f 3080 anda $80,x 1113 anda(0x80,X) #10
|
|
0170 0500 ld [x] 1114 ld([X]) #11
|
|
0171 89ff adda [y,$ff] 1115 adda([Y,oscH]) #12
|
|
0172 89fd adda [y,$fd] 1116 adda([Y,keyH]) #13
|
|
0173 caff st [y,$ff] 1117 st([Y,oscH]) #14
|
|
0174 20fc anda $fc 1118 anda(0xfc) #15
|
|
0175 69fb xora [y,$fb] 1119 xora([Y,wavX]) #16
|
|
0176 1200 ld ac,x 1120 ld(AC,X) #17
|
|
0177 09fa ld [y,$fa] 1121 ld([Y,wavA]) #18
|
|
0178 1407 ld $07,y 1122 ld(soundTable>>8,Y) #19
|
|
0179 8d00 adda [y,x] 1123 adda([Y,X]) #20
|
|
017a e87d blt $017d 1124 bmi(pc()+3) #21
|
|
017b fc7e bra $017e 1125 bra(pc()+3) #22
|
|
017c 203f anda $3f 1126 anda(63) #23
|
|
017d 003f ld $3f 1127 ld(63) #23(!)
|
|
017e 8103 adda [$03] 1128 adda([sample]) #24
|
|
017f c203 st [$03] 1129 st([sample]) #25
|
|
1130
|
|
0180 0113 ld [$13] 1131 ld([xout]) #26 Gets copied to XOUT
|
|
0181 1412 ld $12,y 1132 ld(hi('vBlankLast#34'),Y) #27 Prepare jumping out of page in last line
|
|
0182 191f ld [$1f],out 1133 ld([videoSync0],OUT) #28 End horizontal pulse
|
|
1134
|
|
1135 # Count through the vertical blank interval until its last scan line
|
|
0183 0109 ld [$09] 1136 ld([videoY]) #29
|
|
1137 bpl('.vBlankLast#32') #30
|
|
0184 f4b1 bge .vBlankLast#32
|
|
0185 8002 adda $02 1138 adda(2) #31
|
|
0186 c209 st [$09] 1139 st([videoY]) #32
|
|
1140
|
|
1141 # Determine if we're in the vertical sync pulse
|
|
0187 a0bd suba $bd 1142 suba(1-2*(vBack+vPulse-1)) #33 Prepare sync values
|
|
0188 ec8d bne .prepSync36 1143 bne('.prepSync36') #34 Tests for start of vPulse
|
|
0189 a10d suba [$0d] 1144 suba([videoPulse]) #35
|
|
018a 0040 ld $40 1145 ld(syncBits^vSync) #36 Entering vertical sync pulse
|
|
018b fc92 bra .prepSync39 1146 bra('.prepSync39') #37
|
|
018c c21f st [$1f] 1147 st([videoSync0]) #38
|
|
1148 label('.prepSync36')
|
|
.prepSync36: 018d ec91 bne .prepSync38 1149 bne('.prepSync38') #36 Tests for end of vPulse
|
|
018e 00c0 ld $c0 1150 ld(syncBits) #37
|
|
018f fc93 bra .prepSync40 1151 bra('.prepSync40') #38 Entering vertical back porch
|
|
0190 c21f st [$1f] 1152 st([videoSync0]) #39
|
|
1153 label('.prepSync38')
|
|
.prepSync38: 0191 011f ld [$1f] 1154 ld([videoSync0]) #38 Load current value
|
|
1155 label('.prepSync39')
|
|
.prepSync39: 0192 0200 nop 1156 nop() #39
|
|
1157 label('.prepSync40')
|
|
.prepSync40: 0193 6040 xora $40 1158 xora(hSync) #40 Precompute, as during the pulse there is no time
|
|
0194 c220 st [$20] 1159 st([videoSync1]) #41
|
|
1160
|
|
1161 # Capture the serial input before the '595 shifts it out
|
|
0195 0109 ld [$09] 1162 ld([videoY]) #42 Capture serial input
|
|
0196 60cf xora $cf 1163 xora(1-2*(vBack-1-1)) #43 Exactly when the 74HC595 has captured all 8 controller bits
|
|
0197 ec9a bne $019a 1164 bne(pc()+3) #44
|
|
0198 fc9b bra $019b 1165 bra(pc()+3) #45
|
|
0199 c30f st in,[$0f] 1166 st(IN, [serialRaw]) #46
|
|
019a c000 st $00,[$00] 1167 st(0,[0]) #46(!) Reinitialize carry lookup, for robustness
|
|
1168
|
|
1169 # Update [xout] with the next sound sample every 4 scan lines.
|
|
1170 # Keep doing this on 'videoC equivalent' scan lines in vertical blank.
|
|
019b 0109 ld [$09] 1171 ld([videoY]) #47
|
|
019c 2006 anda $06 1172 anda(6) #48
|
|
1173 beq('vBlankSample') #49
|
|
019d f0a6 beq vBlankSample
|
|
019e 0103 ld [$03] 1174 ld([sample]) #50
|
|
1175
|
|
1176 label('vBlankNormal')
|
|
vBlankNormal: 019f 00a4 ld $a4 1177 runVcpu(199-51, 'AB-D line 1-36')#51 Application cycles (vBlank scan lines without sound sample update)
|
|
01a0 c21e st [$1e]
|
|
01a1 1505 ld [$05],y
|
|
01a2 e0ff jmp y,$ff
|
|
01a3 0035 ld $35
|
|
01a4 fc66 bra sound1 1178 bra('sound1') #199
|
|
01a5 191f ld [$1f],out 1179 ld([videoSync0],OUT) #0 <New scan line start>
|
|
1180
|
|
1181 label('vBlankSample')
|
|
vBlankSample: 01a6 400f ora $0f 1182 ora(0x0f) #51 New sound sample is ready
|
|
01a7 2114 anda [$14] 1183 anda([xoutMask]) #52
|
|
01a8 c213 st [$13] 1184 st([xout]) #53
|
|
01a9 c003 st $03,[$03] 1185 st(sample, [sample]) #54 Reset for next sample
|
|
1186
|
|
01aa 00af ld $af 1187 runVcpu(199-55, '--C- line 3-39')#55 Application cycles (vBlank scan lines with sound sample update)
|
|
01ab c21e st [$1e]
|
|
01ac 1505 ld [$05],y
|
|
01ad e0ff jmp y,$ff
|
|
01ae 0033 ld $33
|
|
01af fc66 bra sound1 1188 bra('sound1') #199
|
|
01b0 191f ld [$1f],out 1189 ld([videoSync0],OUT) #0 <New scan line start>
|
|
1190
|
|
1191 #-----------------------------------------------------------------------
|
|
1192
|
|
1193 label('.vBlankLast#32')
|
|
.vBlankLast#32:
|
|
01b1 e02e jmp y,$2e 1194 jmp(Y,'vBlankLast#34') #32 Jump out of page for space reasons
|
|
1195 #assert hi(controllerType) == hi(pc()) # Assume these share the high address
|
|
01b2 1401 ld $01,y 1196 ld(hi(pc()),Y) #33
|
|
1197
|
|
1198 label('vBlankLast#52')
|
|
1199
|
|
1200 # Respond to reset button (14 cycles)
|
|
1201 # - ResetTimer decrements as long as just [Start] is pressed down
|
|
1202 # - Reaching 0 (normal) or 128 (extended) triggers the soft reset sequence
|
|
1203 # - Initial value is 128 (or 255 at boot), first decrement, then check
|
|
1204 # - This starts vReset -> SYS_Reset_88 -> SYS_Exec_88 -> Reset.gcl -> Main.gcl
|
|
1205 # - Main.gcl then recognizes extended presses if resetTimer is 0..127 ("paasei")
|
|
1206 # - This requires a full cycle (4s) in the warm boot scenario
|
|
1207 # - Or a half cycle (2s) when pressing [Select] down during hard reset
|
|
1208 # - This furthermore requires >=1 frame (and <=128) to have passed between
|
|
1209 # reaching 128 and getting through Reset and the start of Main, while [Start]
|
|
1210 # was still pressed so the count reaches <128. Two reasonable expectations.
|
|
1211 # - The unintended power-up scenarios of ROMv1 (pulling SER_DATA low, or
|
|
1212 # pressing [Select] together with another button) now don't trigger anymore.
|
|
1213
|
|
vBlankLast#52:
|
|
01b3 0111 ld [$11] 1214 ld([buttonState]) #52 Check [Start] for soft reset
|
|
01b4 60ef xora $ef 1215 xora(~buttonStart) #53
|
|
01b5 ecbe bne .restart#56 1216 bne('.restart#56') #54
|
|
01b6 0112 ld [$12] 1217 ld([resetTimer]) #55 As long as button pressed
|
|
01b7 a001 suba $01 1218 suba(1) #56 ... count down the timer
|
|
01b8 c212 st [$12] 1219 st([resetTimer]) #57
|
|
01b9 207f anda $7f 1220 anda(127) #58
|
|
01ba f0c6 beq .restart#61 1221 beq('.restart#61') #59 Reset at 0 (normal 2s) or 128 (extended 4s)
|
|
01bb 00ee ld $ee 1222 ld((vReset&255)-2) #60 Start force reset when hitting 0
|
|
01bc fcc5 bra .restart#63 1223 bra('.restart#63') #61 ... otherwise do nothing yet
|
|
01bd fcc4 bra .restart#64 1224 bra('.restart#64') #62
|
|
1225 label('.restart#56')
|
|
.restart#56: 01be 0001 ld $01 1226 wait(62-56) #56
|
|
01bf ecbf bne $01bf
|
|
01c0 a001 suba $01
|
|
01c1 0200 nop
|
|
01c2 0080 ld $80 1227 ld(128) #62 Not pressed, reset the timer
|
|
01c3 c212 st [$12] 1228 st([resetTimer]) #63
|
|
1229 label('.restart#64')
|
|
.restart#64: 01c4 fccb bra .restart#66 1230 bra('.restart#66') #64
|
|
1231 label('.restart#63')
|
|
.restart#63: 01c5 0200 nop 1232 nop() #63,65
|
|
1233 label('.restart#61')
|
|
.restart#61: 01c6 c216 st [$16] 1234 st([vPC]) #61 Point vPC at vReset
|
|
01c7 0001 ld $01 1235 ld(vReset>>8) #62
|
|
01c8 c217 st [$17] 1236 st([vPC+1]) #63
|
|
01c9 0002 ld $02 1237 ld(hi('ENTER')) #64 Set active interpreter to vCPU
|
|
01ca c205 st [$05] 1238 st([vCpuSelect]) #65
|
|
1239 label('.restart#66')
|
|
1240
|
|
1241 # Switch video mode when (only) select is pressed (16 cycles)
|
|
1242 # XXX We could make this a vCPU interrupt
|
|
.restart#66: 01cb 0111 ld [$11] 1243 ld([buttonState]) #66 Check [Select] to switch modes
|
|
01cc 60df xora $df 1244 xora(~buttonSelect) #67 Only trigger when just [Select] is pressed
|
|
01cd ece2 bne .select#70 1245 bne('.select#70') #68
|
|
01ce 010b ld [$0b] 1246 ld([videoModeC]) #69
|
|
01cf e8d5 blt .select#72 1247 bmi('.select#72') #70 Branch when line C is off
|
|
01d0 010a ld [$0a] 1248 ld([videoModeB]) #71 Rotate: Off->D->B->C
|
|
01d1 c20b st [$0b] 1249 st([videoModeC]) #72
|
|
01d2 010c ld [$0c] 1250 ld([videoModeD]) #73
|
|
01d3 c20a st [$0a] 1251 st([videoModeB]) #74
|
|
01d4 fcda bra .select#77 1252 bra('.select#77') #75
|
|
1253 label('.select#72')
|
|
.select#72: 01d5 00f6 ld $f6 1254 ld('nopixels') #72,76
|
|
01d6 000a ld $0a 1255 ld('pixels') #73 Reset: On->D->B->C
|
|
01d7 c20b st [$0b] 1256 st([videoModeC]) #74
|
|
01d8 c20a st [$0a] 1257 st([videoModeB]) #75
|
|
01d9 0200 nop 1258 nop() #76
|
|
1259 label('.select#77')
|
|
.select#77: 01da c20c st [$0c] 1260 st([videoModeD]) #77
|
|
01db 0035 ld $35 1261 wait(188-78) #78 Don't waste code space expanding runVcpu here
|
|
01dc ecdc bne $01dc
|
|
01dd a001 suba $01
|
|
01de 0200 nop
|
|
1262 # AC==255 now
|
|
01df c211 st [$11] 1263 st([buttonState]) #188
|
|
1264 bra('vBlankEnd#191') #189
|
|
01e0 fcea bra vBlankEnd#191
|
|
01e1 0000 ld $00 1265 ld(0) #190
|
|
1266 label('.select#70')
|
|
1267
|
|
1268 # Mitigation of runaway channel variable
|
|
.select#70: 01e2 0102 ld [$02] 1269 ld([channel]) #70 Normalize channel, for robustness
|
|
01e3 2003 anda $03 1270 anda(0b00000011) #71
|
|
01e4 c202 st [$02] 1271 st([channel]) #72 Stop wild channel updates
|
|
1272
|
|
01e5 00ea ld $ea 1273 runVcpu(191-73, '---D line 40') #73 Application cycles (scan line 40)
|
|
01e6 c21e st [$1e]
|
|
01e7 1505 ld [$05],y
|
|
01e8 e0ff jmp y,$ff
|
|
01e9 0026 ld $26
|
|
1274
|
|
1275 # AC==0 now
|
|
1276 label('vBlankEnd#191')
|
|
vBlankEnd#191:
|
|
01ea 1401 ld $01,y 1277 ld(videoTop_v5>>8,Y) #191
|
|
01eb 09f9 ld [y,$f9] 1278 ld([Y,videoTop_v5]) #192
|
|
01ec c209 st [$09] 1279 st([videoY]) #193
|
|
01ed c21f st [$1f] 1280 st([frameX]) #194
|
|
01ee ecf1 bne $01f1 1281 bne(pc()+3) #195
|
|
01ef fcf2 bra $01f2 1282 bra(pc()+3) #196
|
|
01f0 0001 ld $01 1283 ld('videoA') #197
|
|
01f1 00ec ld $ec 1284 ld('videoF') #197(!)
|
|
01f2 c20d st [$0d] 1285 st([nextVideo]) #198
|
|
01f3 0102 ld [$02] 1286 ld([channel]) #199 Advance to next sound channel
|
|
01f4 2121 anda [$21] 1287 anda([channelMask]) #0 <New scan line start>
|
|
01f5 8001 adda $01 1288 adda(1) #1
|
|
01f6 1402 ld $02,y 1289 ld(hi('sound2'),Y) #2
|
|
01f7 e0b1 jmp y,$b1 1290 jmp(Y,'sound2') #3
|
|
01f8 1880 ld $80,out 1291 ld(syncBits^hSync,OUT) #4 Start horizontal pulse
|
|
1292
|
|
01f9 0200 nop 1293 fillers(until=0xff)
|
|
01fa 0200 nop
|
|
01fb 0200 nop
|
|
* 6 times
|
|
1294
|
|
1295 #-----------------------------------------------------------------------
|
|
1296 # Return point for vCPU slices during visible screen area
|
|
1297 #-----------------------------------------------------------------------
|
|
1298
|
|
1299 assert pc() == 0x1ff # Enables runVcpu() to re-enter into the next page
|
|
01ff fcae bra sound3 1300 bra('sound3') #200,0 <New scan line start>
|
|
1301
|
|
1302 #-----------------------------------------------------------------------
|
|
1303 #
|
|
1304 # $0200 ROM page 2: Video loop visible scanlines
|
|
1305 #
|
|
1306 #-----------------------------------------------------------------------
|
|
1307 align(0x100, size=0x100)
|
|
0200 0102 ld [$02] 1308 ld([channel]) #1 Advance to next sound channel
|
|
1309
|
|
1310 # Back porch A: first of 4 repeated scan lines
|
|
1311 # - Fetch next Yi and store it for retrieval in the next scan lines
|
|
1312 # - Calculate Xi from dXi, but there is no cycle time left to store it as well
|
|
1313 label('videoA')
|
|
videoA: 0201 00ca ld $ca 1314 ld('videoB') #29 1st scanline of 4 (always visible)
|
|
0202 c20d st [$0d] 1315 st([nextVideo]) #30
|
|
0203 1401 ld $01,y 1316 ld(videoTable>>8,Y) #31
|
|
0204 1109 ld [$09],x 1317 ld([videoY],X) #32
|
|
0205 0d00 ld [y,x] 1318 ld([Y,X]) #33
|
|
0206 de00 st [y,x++] 1319 st([Y,Xpp]) #34 Just X++
|
|
0207 c220 st [$20] 1320 st([frameY]) #35
|
|
0208 0d00 ld [y,x] 1321 ld([Y,X]) #36
|
|
0209 911f adda [$1f],x 1322 adda([frameX],X) #37
|
|
1323 label('pixels')
|
|
pixels: 020a 1520 ld [$20],y 1324 ld([frameY],Y) #38
|
|
020b 00c0 ld $c0 1325 ld(syncBits) #39
|
|
1326
|
|
1327 # Stream 160 pixels from memory location <Yi,Xi> onwards
|
|
1328 # Superimpose the sync signal bits to be robust against misprogramming
|
|
1329 for i in range(qqVgaWidth):
|
|
020c 5d00 ora [y,x++],out 1330 ora([Y,Xpp],OUT) #40-199 Pixel burst
|
|
020d 5d00 ora [y,x++],out
|
|
020e 5d00 ora [y,x++],out
|
|
* 160 times
|
|
02ac 18c0 ld $c0,out 1331 ld(syncBits,OUT) #0 <New scan line start> Back to black
|
|
1332
|
|
1333 # Front porch
|
|
02ad 0102 ld [$02] 1334 ld([channel]) #1 Advance to next sound channel
|
|
1335 label('sound3') # Return from vCPU interpreter
|
|
sound3: 02ae 2121 anda [$21] 1336 anda([channelMask]) #2
|
|
02af 8001 adda $01 1337 adda(1) #3
|
|
02b0 1880 ld $80,out 1338 ld(syncBits^hSync,OUT) #4 Start horizontal pulse
|
|
1339
|
|
1340 # Horizontal sync and sound channel update for scanlines outside vBlank
|
|
1341 label('sound2')
|
|
sound2: 02b1 d602 st [$02],y 1342 st([channel],Y) #5
|
|
02b2 007f ld $7f 1343 ld(0x7f) #6
|
|
02b3 29fe anda [y,$fe] 1344 anda([Y,oscL]) #7
|
|
02b4 89fc adda [y,$fc] 1345 adda([Y,keyL]) #8
|
|
02b5 cafe st [y,$fe] 1346 st([Y,oscL]) #9
|
|
02b6 3080 anda $80,x 1347 anda(0x80,X) #10
|
|
02b7 0500 ld [x] 1348 ld([X]) #11
|
|
02b8 89ff adda [y,$ff] 1349 adda([Y,oscH]) #12
|
|
02b9 89fd adda [y,$fd] 1350 adda([Y,keyH]) #13
|
|
02ba caff st [y,$ff] 1351 st([Y,oscH] ) #14
|
|
02bb 20fc anda $fc 1352 anda(0xfc) #15
|
|
02bc 69fb xora [y,$fb] 1353 xora([Y,wavX]) #16
|
|
02bd 1200 ld ac,x 1354 ld(AC,X) #17
|
|
02be 09fa ld [y,$fa] 1355 ld([Y,wavA]) #18
|
|
02bf 1407 ld $07,y 1356 ld(soundTable>>8,Y) #19
|
|
02c0 8d00 adda [y,x] 1357 adda([Y,X]) #20
|
|
02c1 e8c4 blt $02c4 1358 bmi(pc()+3) #21
|
|
02c2 fcc5 bra $02c5 1359 bra(pc()+3) #22
|
|
02c3 203f anda $3f 1360 anda(63) #23
|
|
02c4 003f ld $3f 1361 ld(63) #23(!)
|
|
02c5 8103 adda [$03] 1362 adda([sample]) #24
|
|
02c6 c203 st [$03] 1363 st([sample]) #25
|
|
1364
|
|
02c7 0113 ld [$13] 1365 ld([xout]) #26 Gets copied to XOUT
|
|
02c8 fd0d bra [$0d] 1366 bra([nextVideo]) #27
|
|
02c9 18c0 ld $c0,out 1367 ld(syncBits,OUT) #28 End horizontal pulse
|
|
1368
|
|
1369 # Back porch B: second of 4 repeated scan lines
|
|
1370 # - Recompute Xi from dXi and store for retrieval in the next scan lines
|
|
1371 label('videoB')
|
|
videoB: 02ca 00d3 ld $d3 1372 ld('videoC') #29 2nd scanline of 4
|
|
02cb c20d st [$0d] 1373 st([nextVideo]) #30
|
|
02cc 1401 ld $01,y 1374 ld(videoTable>>8,Y) #31
|
|
02cd 0109 ld [$09] 1375 ld([videoY]) #32
|
|
02ce 9001 adda $01,x 1376 adda(1,X) #33
|
|
02cf 011f ld [$1f] 1377 ld([frameX]) #34
|
|
02d0 8d00 adda [y,x] 1378 adda([Y,X]) #35
|
|
02d1 fd0a bra [$0a] 1379 bra([videoModeB]) #36
|
|
02d2 d21f st [$1f],x 1380 st([frameX],X) #37 Store in RAM and X
|
|
1381
|
|
1382 # Back porch C: third of 4 repeated scan lines
|
|
1383 # - Nothing new to for video do as Yi and Xi are known,
|
|
1384 # - This is the time to emit and reset the next sound sample
|
|
1385 label('videoC')
|
|
videoC: 02d3 00dc ld $dc 1386 ld('videoD') #29 3rd scanline of 4
|
|
02d4 c20d st [$0d] 1387 st([nextVideo]) #30
|
|
02d5 0103 ld [$03] 1388 ld([sample]) #31 New sound sample is ready (didn't fit in the audio loop)
|
|
02d6 400f ora $0f 1389 ora(0x0f) #32
|
|
02d7 2114 anda [$14] 1390 anda([xoutMask]) #33
|
|
02d8 c213 st [$13] 1391 st([xout]) #34 Update [xout] with new sample (4 channels just updated)
|
|
02d9 c003 st $03,[$03] 1392 st(sample, [sample]) #35 Reset for next sample
|
|
02da fd0b bra [$0b] 1393 bra([videoModeC]) #36
|
|
02db 111f ld [$1f],x 1394 ld([frameX],X) #37
|
|
1395
|
|
1396 # Back porch D: last of 4 repeated scan lines
|
|
1397 # - Calculate the next frame index
|
|
1398 # - Decide if this is the last line or not
|
|
1399 label('videoD') # Default video mode
|
|
videoD: 02dc 111f ld [$1f],x 1400 ld([frameX], X) #29 4th scanline of 4
|
|
02dd 0109 ld [$09] 1401 ld([videoY]) #30
|
|
02de a0ee suba $ee 1402 suba((120-1)*2) #31
|
|
1403 beq('.lastpixels#34') #32
|
|
02df f0e5 beq .lastpixels#34
|
|
02e0 80f0 adda $f0 1404 adda(120*2) #33 More pixel lines to go
|
|
02e1 c209 st [$09] 1405 st([videoY]) #34
|
|
02e2 0001 ld $01 1406 ld('videoA') #35
|
|
02e3 fd0c bra [$0c] 1407 bra([videoModeD]) #36
|
|
02e4 c20d st [$0d] 1408 st([nextVideo]) #37
|
|
1409
|
|
1410 label('.lastpixels#34')
|
|
1411 if soundDiscontinuity == 1:
|
|
.lastpixels#34:
|
|
02e5 c003 st $03,[$03] 1412 st(sample, [sample]) #34 Sound continuity
|
|
1413 else:
|
|
1414 nop() #34
|
|
02e6 00e9 ld $e9 1415 ld('videoE') #35 No more pixel lines to go
|
|
02e7 fd0c bra [$0c] 1416 bra([videoModeD]) #36
|
|
02e8 c20d st [$0d] 1417 st([nextVideo]) #37
|
|
1418
|
|
1419 # Back porch "E": after the last line
|
|
1420 # - Go back and and enter vertical blank (program page 2)
|
|
1421 label('videoE') # Exit visible area
|
|
videoE: 02e9 1401 ld $01,y 1422 ld(hi('vBlankStart'),Y) #29 Return to vertical blank interval
|
|
02ea e004 jmp y,$04 1423 jmp(Y,'vBlankStart') #30
|
|
02eb 00c0 ld $c0 1424 ld(syncBits) #31
|
|
1425
|
|
1426 # Video mode that blacks out one or more pixel lines from the top of screen.
|
|
1427 # This yields some speed, but also frees up screen memory for other purposes.
|
|
1428 # Note: Sound output becomes choppier the more pixel lines are skipped
|
|
1429 # Note: The vertical blank driver leaves 0x80 behind in [videoSync1]
|
|
1430 label('videoF')
|
|
videoF: 02ec 0120 ld [$20] 1431 ld([videoSync1]) #29 Completely black pixel line
|
|
02ed 8080 adda $80 1432 adda(0x80) #30
|
|
02ee d220 st [$20],x 1433 st([videoSync1],X) #31
|
|
02ef 011f ld [$1f] 1434 ld([frameX]) #32
|
|
02f0 a500 suba [x] 1435 suba([X]) #33 Decrements every two VGA scanlines
|
|
02f1 f0f4 beq .videoF#36 1436 beq('.videoF#36') #34
|
|
02f2 c21f st [$1f] 1437 st([frameX]) #35
|
|
02f3 fcf6 bra nopixels 1438 bra('nopixels') #36
|
|
1439 label('.videoF#36')
|
|
.videoF#36: 02f4 0001 ld $01 1440 ld('videoA') #36,37 Transfer to visible screen area
|
|
02f5 c20d st [$0d] 1441 st([nextVideo]) #37
|
|
1442 #
|
|
1443 # Alternative for pixel burst: faster application mode
|
|
1444 label('nopixels')
|
|
nopixels: 02f6 00ff ld $ff 1445 runVcpu(200-38, 'ABCD line 40-520',
|
|
02f7 c21e st [$1e]
|
|
02f8 1505 ld [$05],y
|
|
02f9 e0ff jmp y,$ff
|
|
02fa 003c ld $3c
|
|
1446 returnTo=0x1ff) #38 Application interpreter (black scanlines)
|
|
1447
|
|
1448 #-----------------------------------------------------------------------
|
|
1449 #
|
|
1450 # $0300 ROM page 3: Application interpreter primary page
|
|
1451 #
|
|
1452 #-----------------------------------------------------------------------
|
|
1453
|
|
1454 # Enter the timing-aware application interpreter (aka virtual CPU, vCPU)
|
|
1455 #
|
|
1456 # This routine will execute as many as possible instructions in the
|
|
1457 # allotted time. When time runs out, it synchronizes such that the total
|
|
1458 # duration matches the caller's request. Durations are counted in `ticks',
|
|
1459 # which are multiples of 2 clock cycles.
|
|
1460 #
|
|
1461 # Synopsis: Use the runVcpu() macro as entry point
|
|
1462
|
|
1463 # We let 'ENTER' begin one word before the page boundary, for a bit extra
|
|
1464 # precious space in the packed interpreter code page. Although ENTER's
|
|
1465 # first instruction is bra() which normally doesn't cross page boundaries,
|
|
1466 # in this case it will still jump into the right space, because branches
|
|
1467 # from $xxFF land in the next page anyway.
|
|
1468 while pc()&255 < 255:
|
|
02fb 0200 nop 1469 nop()
|
|
02fc 0200 nop
|
|
02fd 0200 nop
|
|
02fe 0200 nop
|
|
1470 label('ENTER')
|
|
ENTER: 02ff fc03 bra .next2 1471 bra('.next2') #0 Enter at '.next2' (so no startup overhead)
|
|
1472 # --- Page boundary ---
|
|
1473 align(0x100,size=0x100)
|
|
1474 label('NEXTY') # Alternative for REENTER
|
|
NEXTY: 0300 1517 ld [$17],y 1475 ld([vPC+1],Y) #1
|
|
1476
|
|
1477 # Fetch next instruction and execute it, but only if there are sufficient
|
|
1478 # ticks left for the slowest instruction.
|
|
1479 label('NEXT')
|
|
NEXT: 0301 8115 adda [$15] 1480 adda([vTicks]) #0 Track elapsed ticks (actually counting down: AC<0)
|
|
0302 e80b blt EXIT 1481 blt('EXIT') #1 Escape near time out
|
|
1482 label('.next2')
|
|
.next2: 0303 c215 st [$15] 1483 st([vTicks]) #2
|
|
0304 0116 ld [$16] 1484 ld([vPC]) #3 Advance vPC
|
|
0305 8002 adda $02 1485 adda(2) #4
|
|
0306 d216 st [$16],x 1486 st([vPC],X) #5
|
|
0307 0d00 ld [y,x] 1487 ld([Y,X]) #6 Fetch opcode (actually a branch target)
|
|
0308 de00 st [y,x++] 1488 st([Y,Xpp]) #7 Just X++
|
|
0309 fe00 bra ac 1489 bra(AC) #8 Dispatch
|
|
030a 0d00 ld [y,x] 1490 ld([Y,X]) #9 Prefetch operand
|
|
1491
|
|
1492 # Resync with video driver and transfer control
|
|
1493 label('EXIT')
|
|
EXIT: 030b 800e adda $0e 1494 adda(maxTicks) #3
|
|
1495 label('RESYNC')
|
|
RESYNC: 030c e40c bgt RESYNC 1496 bgt(pc()&255) #4 Resync
|
|
030d a001 suba $01 1497 suba(1) #5
|
|
030e 1401 ld $01,y 1498 ld(hi('vBlankStart'),Y) #6
|
|
030f e11e jmp y,[$1e] 1499 jmp(Y,[vReturn]) #7 To video driver
|
|
0310 0000 ld $00 1500 ld(0) #8 AC should be 0 already. Still..
|
|
1501 assert vCPU_overhead == 9
|
|
1502
|
|
1503 # Instruction LDWI: Load immediate word constant (vAC=D), 20 cycles
|
|
1504 label('LDWI')
|
|
LDWI: 0311 c218 st [$18] 1505 st([vAC]) #10
|
|
0312 de00 st [y,x++] 1506 st([Y,Xpp]) #11 Just X++
|
|
0313 0d00 ld [y,x] 1507 ld([Y,X]) #12 Fetch second operand
|
|
0314 c219 st [$19] 1508 st([vAC+1]) #13
|
|
0315 0116 ld [$16] 1509 ld([vPC]) #14 Advance vPC one more
|
|
0316 8001 adda $01 1510 adda(1) #15
|
|
0317 c216 st [$16] 1511 st([vPC]) #16
|
|
0318 00f6 ld $f6 1512 ld(-20/2) #17
|
|
0319 fc01 bra NEXT 1513 bra('NEXT') #18
|
|
1514 #dummy() #19 Overlap
|
|
1515 #
|
|
1516 # Instruction LD: Load byte from zero page (vAC=[D]), 22 cycles
|
|
1517 label('LD')
|
|
LD: 031a 1200 ld ac,x 1518 ld(AC,X) #10,19
|
|
031b 0500 ld [x] 1519 ld([X]) #11
|
|
031c 1404 ld $04,y 1520 ld(hi('ld#15'),Y) #12
|
|
031d e013 jmp y,$13 1521 jmp(Y,'ld#15') #13
|
|
031e c218 st [$18] 1522 st([vAC]) #14
|
|
1523
|
|
1524 # Instruction CMPHS: Adjust high byte for signed compare (vACH=XXX), 28 cycles
|
|
1525 label('CMPHS_v5')
|
|
CMPHS_v5: 031f 140b ld $0b,y 1526 ld(hi('cmphs#13'),Y) #10
|
|
0320 e0bc jmp y,$bc 1527 jmp(Y,'cmphs#13') #11
|
|
1528 #ld(AC,X) #12 Overlap
|
|
1529 #
|
|
1530 # Instruction LDW: Load word from zero page (vAC=[D]+256*[D+1]), 20 cycles
|
|
1531 label('LDW')
|
|
LDW: 0321 1200 ld ac,x 1532 ld(AC,X) #10,12
|
|
0322 8001 adda $01 1533 adda(1) #11
|
|
0323 c21d st [$1d] 1534 st([vTmp]) #12 Address of high byte
|
|
0324 0500 ld [x] 1535 ld([X]) #13
|
|
0325 c218 st [$18] 1536 st([vAC]) #14
|
|
0326 111d ld [$1d],x 1537 ld([vTmp],X) #15
|
|
0327 0500 ld [x] 1538 ld([X]) #16
|
|
0328 c219 st [$19] 1539 st([vAC+1]) #17
|
|
0329 fc01 bra NEXT 1540 bra('NEXT') #18
|
|
032a 00f6 ld $f6 1541 ld(-20/2) #19
|
|
1542
|
|
1543 # Instruction STW: Store word in zero page ([D],[D+1]=vAC&255,vAC>>8), 20 cycles
|
|
1544 label('STW')
|
|
STW: 032b 1200 ld ac,x 1545 ld(AC,X) #10,20
|
|
032c 8001 adda $01 1546 adda(1) #11
|
|
032d c21d st [$1d] 1547 st([vTmp]) #12 Address of high byte
|
|
032e 0118 ld [$18] 1548 ld([vAC]) #13
|
|
032f c600 st [x] 1549 st([X]) #14
|
|
0330 111d ld [$1d],x 1550 ld([vTmp],X) #15
|
|
0331 0119 ld [$19] 1551 ld([vAC+1]) #16
|
|
0332 c600 st [x] 1552 st([X]) #17
|
|
0333 fc01 bra NEXT 1553 bra('NEXT') #18
|
|
0334 00f6 ld $f6 1554 ld(-20/2) #19
|
|
1555
|
|
1556 # Instruction BCC: Test AC sign and branch conditionally, 28 cycles
|
|
1557 label('BCC')
|
|
BCC: 0335 0119 ld [$19] 1558 ld([vAC+1]) #10 First inspect high byte of vAC
|
|
0336 ec40 bne .bcc#13 1559 bne('.bcc#13') #11
|
|
0337 c21d st [$1d] 1560 st([vTmp]) #12
|
|
0338 0118 ld [$18] 1561 ld([vAC]) #13 Additionally inspect low byte of vAC
|
|
0339 f043 beq .bcc#16 1562 beq('.bcc#16') #14
|
|
033a 0001 ld $01 1563 ld(1) #15
|
|
033b c21d st [$1d] 1564 st([vTmp]) #16
|
|
033c 0d00 ld [y,x] 1565 ld([Y,X]) #17 Operand is the conditional
|
|
1566 label('.bcc#18')
|
|
.bcc#18: 033d fe00 bra ac 1567 bra(AC) #18
|
|
033e 011d ld [$1d] 1568 ld([vTmp]) #19
|
|
1569
|
|
1570 # Conditional EQ: Branch if zero (if(vACL==0)vPCL=D)
|
|
1571 label('EQ')
|
|
EQ: 033f ec45 bne .bcc#22 1572 bne('.bcc#22') #20
|
|
1573 label('.bcc#13')
|
|
.bcc#13: 0340 f048 beq .bcc#23 1574 beq('.bcc#23') #21,13 AC=0 in EQ, AC!=0 from BCC... Overlap with BCC
|
|
0341 0d00 ld [y,x] 1575 ld([Y,X]) #22,14 Overlap with BCC
|
|
1576 #
|
|
1577 # (continue BCC)
|
|
1578 #label('.bcc#13')
|
|
1579 #dummy() #13
|
|
1580 #dummy() #14
|
|
0342 0200 nop 1581 nop() #15
|
|
1582 label('.bcc#16')
|
|
.bcc#16: 0343 fc3d bra .bcc#18 1583 bra('.bcc#18') #16
|
|
0344 0d00 ld [y,x] 1584 ld([Y,X]) #17 Operand is the conditional
|
|
1585 label('.bcc#22')
|
|
.bcc#22: 0345 0116 ld [$16] 1586 ld([vPC]) #22 False condition
|
|
0346 fc4a bra .bcc#25 1587 bra('.bcc#25') #23
|
|
0347 8001 adda $01 1588 adda(1) #24
|
|
1589 label('.bcc#23')
|
|
.bcc#23: 0348 de00 st [y,x++] 1590 st([Y,Xpp]) #23 Just X++ True condition
|
|
0349 0d00 ld [y,x] 1591 ld([Y,X]) #24
|
|
1592 label('.bcc#25')
|
|
.bcc#25: 034a c216 st [$16] 1593 st([vPC]) #25
|
|
034b fc01 bra NEXT 1594 bra('NEXT') #26
|
|
034c 00f2 ld $f2 1595 ld(-28/2) #27
|
|
1596
|
|
1597 # Conditional GT: Branch if positive (if(vACL>0)vPCL=D)
|
|
1598 label('GT')
|
|
GT: 034d f845 ble .bcc#22 1599 ble('.bcc#22') #20
|
|
034e e448 bgt .bcc#23 1600 bgt('.bcc#23') #21
|
|
034f 0d00 ld [y,x] 1601 ld([Y,X]) #22
|
|
1602
|
|
1603 # Conditional LT: Branch if negative (if(vACL<0)vPCL=D)
|
|
1604 label('LT')
|
|
LT: 0350 f445 bge .bcc#22 1605 bge('.bcc#22') #20
|
|
0351 e848 blt .bcc#23 1606 blt('.bcc#23') #21
|
|
0352 0d00 ld [y,x] 1607 ld([Y,X]) #22
|
|
1608
|
|
1609 # Conditional GE: Branch if positive or zero (if(vACL>=0)vPCL=D)
|
|
1610 label('GE')
|
|
GE: 0353 e845 blt .bcc#22 1611 blt('.bcc#22') #20
|
|
0354 f448 bge .bcc#23 1612 bge('.bcc#23') #21
|
|
0355 0d00 ld [y,x] 1613 ld([Y,X]) #22
|
|
1614
|
|
1615 # Conditional LE: Branch if negative or zero (if(vACL<=0)vPCL=D)
|
|
1616 label('LE')
|
|
LE: 0356 e445 bgt .bcc#22 1617 bgt('.bcc#22') #20
|
|
0357 f848 ble .bcc#23 1618 ble('.bcc#23') #21
|
|
0358 0d00 ld [y,x] 1619 ld([Y,X]) #22
|
|
1620
|
|
1621 # Instruction LDI: Load immediate small positive constant (vAC=D), 16 cycles
|
|
1622 label('LDI')
|
|
LDI: 0359 c218 st [$18] 1623 st([vAC]) #10
|
|
035a 0000 ld $00 1624 ld(0) #11
|
|
035b c219 st [$19] 1625 st([vAC+1]) #12
|
|
035c fc00 bra NEXTY 1626 bra('NEXTY') #13
|
|
035d 00f8 ld $f8 1627 ld(-16/2) #14
|
|
1628
|
|
1629 # Instruction ST: Store byte in zero page ([D]=vAC&255), 16 cycles
|
|
1630 label('ST')
|
|
ST: 035e 1200 ld ac,x 1631 ld(AC,X) #10,15
|
|
035f 0118 ld [$18] 1632 ld([vAC]) #11
|
|
0360 c600 st [x] 1633 st([X]) #12
|
|
0361 fc00 bra NEXTY 1634 bra('NEXTY') #13
|
|
0362 00f8 ld $f8 1635 ld(-16/2) #14
|
|
1636
|
|
1637 # Instruction POP: Pop address from stack (vLR,vSP==[vSP]+256*[vSP+1],vSP+2), 26 cycles
|
|
1638 label('POP')
|
|
POP: 0363 111c ld [$1c],x 1639 ld([vSP],X) #10,15
|
|
0364 0500 ld [x] 1640 ld([X]) #11
|
|
0365 c21a st [$1a] 1641 st([vLR]) #12
|
|
0366 011c ld [$1c] 1642 ld([vSP]) #13
|
|
0367 9001 adda $01,x 1643 adda(1,X) #14
|
|
0368 0500 ld [x] 1644 ld([X]) #15
|
|
0369 c21b st [$1b] 1645 st([vLR+1]) #16
|
|
036a 011c ld [$1c] 1646 ld([vSP]) #17
|
|
036b 8002 adda $02 1647 adda(2) #18
|
|
036c c21c st [$1c] 1648 st([vSP]) #19
|
|
1649 label('.pop#20')
|
|
.pop#20: 036d 0116 ld [$16] 1650 ld([vPC]) #20
|
|
036e a001 suba $01 1651 suba(1) #21
|
|
036f c216 st [$16] 1652 st([vPC]) #22
|
|
0370 fc00 bra NEXTY 1653 bra('NEXTY') #23
|
|
0371 00f3 ld $f3 1654 ld(-26/2) #24
|
|
1655
|
|
1656 # Conditional NE: Branch if not zero (if(vACL!=0)vPCL=D)
|
|
1657 label('NE')
|
|
NE: 0372 f045 beq .bcc#22 1658 beq('.bcc#22') #20,25
|
|
0373 ec48 bne .bcc#23 1659 bne('.bcc#23') #21
|
|
0374 0d00 ld [y,x] 1660 ld([Y,X]) #22
|
|
1661
|
|
1662 # Instruction PUSH: Push vLR on stack ([vSP-2],v[vSP-1],vSP=vLR&255,vLR>>8,vLR-2), 26 cycles
|
|
1663 label('PUSH')
|
|
PUSH: 0375 011c ld [$1c] 1664 ld([vSP]) #10
|
|
0376 b001 suba $01,x 1665 suba(1,X) #11
|
|
0377 011b ld [$1b] 1666 ld([vLR+1]) #12
|
|
0378 c600 st [x] 1667 st([X]) #13
|
|
0379 011c ld [$1c] 1668 ld([vSP]) #14
|
|
037a a002 suba $02 1669 suba(2) #15
|
|
037b d21c st [$1c],x 1670 st([vSP],X) #16
|
|
037c 011a ld [$1a] 1671 ld([vLR]) #17
|
|
037d fc6d bra .pop#20 1672 bra('.pop#20') #18
|
|
037e c600 st [x] 1673 st([X]) #19
|
|
1674
|
|
1675 # Instruction LUP: ROM lookup (vAC=ROM[vAC+D]), 26 cycles
|
|
1676 label('LUP')
|
|
LUP: 037f 1519 ld [$19],y 1677 ld([vAC+1],Y) #10
|
|
0380 e0fb jmp y,$fb 1678 jmp(Y,251) #11 Trampoline offset
|
|
0381 8118 adda [$18] 1679 adda([vAC]) #12
|
|
1680
|
|
1681 # Instruction ANDI: Logical-AND with small constant (vAC&=D), 22 cycles
|
|
1682 label('ANDI')
|
|
ANDI: 0382 1404 ld $04,y 1683 ld(hi('andi#13'),Y) #10
|
|
0383 e011 jmp y,$11 1684 jmp(Y,'andi#13') #11
|
|
0384 2118 anda [$18] 1685 anda([vAC]) #12
|
|
1686
|
|
1687 # Instruction CALLI: Goto immediate address and remember vPC (vLR,vPC=vPC+3,$HHLL-2), 28 cycles
|
|
1688 label('CALLI_v5')
|
|
CALLI_v5: 0385 140b ld $0b,y 1689 ld(hi('calli#13'),Y) #10
|
|
0386 e0b0 jmp y,$b0 1690 jmp(Y,'calli#13') #11
|
|
0387 0116 ld [$16] 1691 ld([vPC]) #12
|
|
1692
|
|
1693 # Instruction ORI: Logical-OR with small constant (vAC|=D), 14 cycles
|
|
1694 label('ORI')
|
|
ORI: 0388 4118 ora [$18] 1695 ora([vAC]) #10
|
|
0389 c218 st [$18] 1696 st([vAC]) #11
|
|
038a fc01 bra NEXT 1697 bra('NEXT') #12
|
|
038b 00f9 ld $f9 1698 ld(-14/2) #13
|
|
1699
|
|
1700 # Instruction XORI: Logical-XOR with small constant (vAC^=D), 14 cycles
|
|
1701 label('XORI')
|
|
XORI: 038c 6118 xora [$18] 1702 xora([vAC]) #10
|
|
038d c218 st [$18] 1703 st([vAC]) #11
|
|
038e fc01 bra NEXT 1704 bra('NEXT') #12
|
|
038f 00f9 ld $f9 1705 ld(-14/2) #13
|
|
1706
|
|
1707 # Instruction BRA: Branch unconditionally (vPC=(vPC&0xff00)+D), 14 cycles
|
|
1708 label('BRA')
|
|
BRA: 0390 c216 st [$16] 1709 st([vPC]) #10
|
|
0391 fc00 bra NEXTY 1710 bra('NEXTY') #11
|
|
0392 00f9 ld $f9 1711 ld(-14/2) #12
|
|
1712
|
|
1713 # Instruction INC: Increment zero page byte ([D]++), 20 cycles
|
|
1714 label('INC')
|
|
INC: 0393 1200 ld ac,x 1715 ld(AC,X) #10,13
|
|
0394 1404 ld $04,y 1716 ld(hi('inc#14'),Y) #11
|
|
0395 e0e4 jmp y,$e4 1717 jmp(Y,'inc#14') #12
|
|
0396 0001 ld $01 1718 ld(1) #13
|
|
1719
|
|
1720 # Instruction CMPHU: Adjust high byte for unsigned compare (vACH=XXX), 28 cycles
|
|
1721 label('CMPHU_v5')
|
|
CMPHU_v5: 0397 140b ld $0b,y 1722 ld(hi('cmphu#13'),Y) #10
|
|
0398 e0c8 jmp y,$c8 1723 jmp(Y,'cmphu#13') #11
|
|
1724 #ld(AC,X) #12 Overlap
|
|
1725 #
|
|
1726 # Instruction ADDW: Word addition with zero page (vAC+=[D]+256*[D+1]), 28 cycles
|
|
1727 label('ADDW')
|
|
1728 # The non-carry paths could be 26 cycles at the expense of (much) more code.
|
|
1729 # But a smaller size is better so more instructions fit in this code page.
|
|
1730 # 28 cycles is still 4.5 usec. The 6502 equivalent takes 20 cycles or 20 usec.
|
|
ADDW: 0399 1200 ld ac,x 1731 ld(AC,X) #10,12 Address of low byte to be added
|
|
039a 8001 adda $01 1732 adda(1) #11
|
|
039b c21d st [$1d] 1733 st([vTmp]) #12 Address of high byte to be added
|
|
039c 0118 ld [$18] 1734 ld([vAC]) #13 Add the low bytes
|
|
039d 8500 adda [x] 1735 adda([X]) #14
|
|
039e c218 st [$18] 1736 st([vAC]) #15 Store low result
|
|
039f e8a3 blt .addw#18 1737 bmi('.addw#18') #16 Now figure out if there was a carry
|
|
03a0 a500 suba [x] 1738 suba([X]) #17 Gets back the initial value of vAC
|
|
03a1 fca5 bra .addw#20 1739 bra('.addw#20') #18
|
|
03a2 4500 ora [x] 1740 ora([X]) #19 Carry in bit 7
|
|
1741 label('.addw#18')
|
|
.addw#18: 03a3 2500 anda [x] 1742 anda([X]) #18 Carry in bit 7
|
|
03a4 0200 nop 1743 nop() #19
|
|
1744 label('.addw#20')
|
|
.addw#20: 03a5 3080 anda $80,x 1745 anda(0x80,X) #20 Move carry to bit 0
|
|
03a6 0500 ld [x] 1746 ld([X]) #21
|
|
03a7 8119 adda [$19] 1747 adda([vAC+1]) #22 Add the high bytes with carry
|
|
03a8 111d ld [$1d],x 1748 ld([vTmp],X) #23
|
|
03a9 8500 adda [x] 1749 adda([X]) #24
|
|
03aa c219 st [$19] 1750 st([vAC+1]) #25 Store high result
|
|
03ab fc01 bra NEXT 1751 bra('NEXT') #26
|
|
03ac 00f2 ld $f2 1752 ld(-28/2) #27
|
|
1753
|
|
1754 # Instruction PEEK: Read byte from memory (vAC=[vAC]), 26 cycles
|
|
1755 label('PEEK')
|
|
PEEK: 03ad 1404 ld $04,y 1756 ld(hi('peek'),Y) #10
|
|
03ae e062 jmp y,$62 1757 jmp(Y,'peek') #11
|
|
1758 #ld([vPC]) #12 Overlap
|
|
1759 #
|
|
1760 # Instruction SYS: Native call, <=256 cycles (<=128 ticks, in reality less)
|
|
1761 #
|
|
1762 # The 'SYS' vCPU instruction first checks the number of desired ticks given by
|
|
1763 # the operand. As long as there are insufficient ticks available in the current
|
|
1764 # time slice, the instruction will be retried. This will effectively wait for
|
|
1765 # the next scan line if the current slice is almost out of time. Then a jump to
|
|
1766 # native code is made. This code can do whatever it wants, but it must return
|
|
1767 # to the 'REENTER' label when done. When returning, AC must hold (the negative
|
|
1768 # of) the actual consumed number of whole ticks for the entire virtual
|
|
1769 # instruction cycle (from NEXT to NEXT). This duration may not exceed the prior
|
|
1770 # declared duration in the operand + 28 (or maxTicks). The operand specifies the
|
|
1771 # (negative) of the maximum number of *extra* ticks that the native call will
|
|
1772 # need. The GCL compiler automatically makes this calculation from gross number
|
|
1773 # of cycles to excess number of ticks.
|
|
1774 # SYS functions can modify vPC to implement repetition. For example to split
|
|
1775 # up work into multiple chucks.
|
|
1776 label('.sys#13')
|
|
.sys#13: 03af 0116 ld [$16] 1777 ld([vPC]) #13,12 Retry until sufficient time
|
|
03b0 a002 suba $02 1778 suba(2) #14
|
|
03b1 c216 st [$16] 1779 st([vPC]) #15
|
|
03b2 fccb bra REENTER 1780 bra('REENTER') #16
|
|
03b3 00f6 ld $f6 1781 ld(-20/2) #17
|
|
1782 label('SYS')
|
|
SYS: 03b4 8115 adda [$15] 1783 adda([vTicks]) #10
|
|
03b5 e8af blt .sys#13 1784 blt('.sys#13') #11
|
|
03b6 1523 ld [$23],y 1785 ld([sysFn+1],Y) #12
|
|
03b7 e122 jmp y,[$22] 1786 jmp(Y,[sysFn]) #13
|
|
1787 #dummy() #14 Overlap
|
|
1788 #
|
|
1789 # Instruction SUBW: Word subtract with zero page (AC-=[D]+256*[D+1]), 28 cycles
|
|
1790 # All cases can be done in 26 cycles, but the code will become much larger
|
|
1791 label('SUBW')
|
|
SUBW: 03b8 1200 ld ac,x 1792 ld(AC,X) #10,14 Address of low byte to be subtracted
|
|
03b9 8001 adda $01 1793 adda(1) #11
|
|
03ba c21d st [$1d] 1794 st([vTmp]) #12 Address of high byte to be subtracted
|
|
03bb 0118 ld [$18] 1795 ld([vAC]) #13
|
|
03bc e8c1 blt .subw#16 1796 bmi('.subw#16') #14
|
|
03bd a500 suba [x] 1797 suba([X]) #15
|
|
03be c218 st [$18] 1798 st([vAC]) #16 Store low result
|
|
03bf fcc4 bra .subw#19 1799 bra('.subw#19') #17
|
|
03c0 4500 ora [x] 1800 ora([X]) #18 Carry in bit 7
|
|
1801 label('.subw#16')
|
|
.subw#16: 03c1 c218 st [$18] 1802 st([vAC]) #16 Store low result
|
|
03c2 2500 anda [x] 1803 anda([X]) #17 Carry in bit 7
|
|
03c3 0200 nop 1804 nop() #18
|
|
1805 label('.subw#19')
|
|
.subw#19: 03c4 3080 anda $80,x 1806 anda(0x80,X) #19 Move carry to bit 0
|
|
03c5 0119 ld [$19] 1807 ld([vAC+1]) #20
|
|
03c6 a500 suba [x] 1808 suba([X]) #21
|
|
03c7 111d ld [$1d],x 1809 ld([vTmp],X) #22
|
|
03c8 a500 suba [x] 1810 suba([X]) #23
|
|
03c9 c219 st [$19] 1811 st([vAC+1]) #24
|
|
1812 label('REENTER_28')
|
|
REENTER_28: 03ca 00f2 ld $f2 1813 ld(-28/2) #25
|
|
1814 label('REENTER')
|
|
REENTER: 03cb fc01 bra NEXT 1815 bra('NEXT') #26 Return from SYS calls
|
|
03cc 1517 ld [$17],y 1816 ld([vPC+1],Y) #27
|
|
1817
|
|
1818 # Instruction DEF: Define data or code (vAC,vPC=vPC+2,(vPC&0xff00)+D), 24 cycles
|
|
1819 label('DEF')
|
|
DEF: 03cd 1404 ld $04,y 1820 ld(hi('def#13'),Y) #10
|
|
03ce e007 jmp y,$07 1821 jmp(Y,'def#13') #11
|
|
1822 #st([vTmp]) #12 Overlap
|
|
1823 #
|
|
1824 # Instruction CALL: Goto address and remember vPC (vLR,vPC=vPC+2,[D]+256*[D+1]-2), 26 cycles
|
|
1825 label('CALL')
|
|
CALL: 03cf c21d st [$1d] 1826 st([vTmp]) #10,12
|
|
03d0 0116 ld [$16] 1827 ld([vPC]) #11
|
|
03d1 8002 adda $02 1828 adda(2) #12 Point to instruction after CALL
|
|
03d2 c21a st [$1a] 1829 st([vLR]) #13
|
|
03d3 0117 ld [$17] 1830 ld([vPC+1]) #14
|
|
03d4 c21b st [$1b] 1831 st([vLR+1]) #15
|
|
03d5 111d ld [$1d],x 1832 ld([vTmp],X) #16
|
|
03d6 0500 ld [x] 1833 ld([X]) #17
|
|
03d7 a002 suba $02 1834 suba(2) #18 Because NEXT will add 2
|
|
03d8 c216 st [$16] 1835 st([vPC]) #19
|
|
03d9 011d ld [$1d] 1836 ld([vTmp]) #20
|
|
03da 9001 adda $01,x 1837 adda(1,X) #21
|
|
03db 0500 ld [x] 1838 ld([X]) #22
|
|
03dc d617 st [$17],y 1839 st([vPC+1],Y) #23
|
|
03dd fc01 bra NEXT 1840 bra('NEXT') #24
|
|
03de 00f3 ld $f3 1841 ld(-26/2) #25
|
|
1842
|
|
1843 # Instruction ALLOC: Create or destroy stack frame (vSP+=D), 14 cycles
|
|
1844 label('ALLOC')
|
|
ALLOC: 03df 811c adda [$1c] 1845 adda([vSP]) #10
|
|
03e0 c21c st [$1c] 1846 st([vSP]) #11
|
|
03e1 fc01 bra NEXT 1847 bra('NEXT') #12
|
|
03e2 00f9 ld $f9 1848 ld(-14/2) #13
|
|
1849
|
|
1850 # The instructions below are all implemented in the second code page. Jumping
|
|
1851 # back and forth makes each 6 cycles slower, but it also saves space in the
|
|
1852 # primary page for the instructions above. Most of them are in fact not very
|
|
1853 # critical, as evidenced by the fact that they weren't needed for the first
|
|
1854 # Gigatron applications (Snake, Racer, Mandelbrot, Loader). By providing them
|
|
1855 # in this way, at least they don't need to be implemented as a SYS extension.
|
|
1856
|
|
1857 # Instruction ADDI: Add small positive constant (vAC+=D), 28 cycles
|
|
1858 label('ADDI')
|
|
ADDI: 03e3 1404 ld $04,y 1859 ld(hi('addi'),Y) #10
|
|
03e4 e018 jmp y,$18 1860 jmp(Y,'addi') #11
|
|
03e5 c21d st [$1d] 1861 st([vTmp]) #12
|
|
1862
|
|
1863 # Instruction SUBI: Subtract small positive constant (vAC+=D), 28 cycles
|
|
1864 label('SUBI')
|
|
SUBI: 03e6 1404 ld $04,y 1865 ld(hi('subi'),Y) #10
|
|
03e7 e026 jmp y,$26 1866 jmp(Y,'subi') #11
|
|
03e8 c21d st [$1d] 1867 st([vTmp]) #12
|
|
1868
|
|
1869 # Instruction LSLW: Logical shift left (vAC<<=1), 28 cycles
|
|
1870 # Useful, because ADDW can't add vAC to itself. Also more compact.
|
|
1871 label('LSLW')
|
|
LSLW: 03e9 1404 ld $04,y 1872 ld(hi('lslw'),Y) #10
|
|
03ea e035 jmp y,$35 1873 jmp(Y,'lslw') #11
|
|
03eb 0118 ld [$18] 1874 ld([vAC]) #12
|
|
1875
|
|
1876 # Instruction STLW: Store word in stack frame ([vSP+D],[vSP+D+1]=vAC&255,vAC>>8), 26 cycles
|
|
1877 label('STLW')
|
|
STLW: 03ec 1404 ld $04,y 1878 ld(hi('stlw'),Y) #10
|
|
03ed e041 jmp y,$41 1879 jmp(Y,'stlw') #11
|
|
1880 #dummy() #12 Overlap
|
|
1881 #
|
|
1882 # Instruction LDLW: Load word from stack frame (vAC=[vSP+D]+256*[vSP+D+1]), 26 cycles
|
|
1883 label('LDLW')
|
|
LDLW: 03ee 1404 ld $04,y 1884 ld(hi('ldlw'),Y) #10,12
|
|
03ef e04c jmp y,$4c 1885 jmp(Y,'ldlw') #11
|
|
1886 #dummy() #12 Overlap
|
|
1887 #
|
|
1888 # Instruction POKE: Write byte in memory ([[D+1],[D]]=vAC&255), 28 cycles
|
|
1889 label('POKE')
|
|
POKE: 03f0 1404 ld $04,y 1890 ld(hi('poke'),Y) #10,12
|
|
03f1 e057 jmp y,$57 1891 jmp(Y,'poke') #11
|
|
03f2 c21d st [$1d] 1892 st([vTmp]) #12
|
|
1893
|
|
1894 # Instruction DOKE: Write word in memory ([[D+1],[D]],[[D+1],[D]+1]=vAC&255,vAC>>8), 28 cycles
|
|
1895 label('DOKE')
|
|
DOKE: 03f3 1404 ld $04,y 1896 ld(hi('doke'),Y) #10
|
|
03f4 e06d jmp y,$6d 1897 jmp(Y,'doke') #11
|
|
03f5 c21d st [$1d] 1898 st([vTmp]) #12
|
|
1899
|
|
1900 # Instruction DEEK: Read word from memory (vAC=[vAC]+256*[vAC+1]), 28 cycles
|
|
1901 label('DEEK')
|
|
DEEK: 03f6 1404 ld $04,y 1902 ld(hi('deek'),Y) #10
|
|
03f7 e07a jmp y,$7a 1903 jmp(Y,'deek') #11
|
|
1904 #dummy() #12 Overlap
|
|
1905 #
|
|
1906 # Instruction ANDW: Word logical-AND with zero page (vAC&=[D]+256*[D+1]), 28 cycles
|
|
1907 label('ANDW')
|
|
ANDW: 03f8 1404 ld $04,y 1908 ld(hi('andw'),Y) #10,12
|
|
03f9 e086 jmp y,$86 1909 jmp(Y,'andw') #11
|
|
1910 #dummy() #12 Overlap
|
|
1911 #
|
|
1912 # Instruction ORW: Word logical-OR with zero page (vAC|=[D]+256*[D+1]), 28 cycles
|
|
1913 label('ORW')
|
|
ORW: 03fa 1404 ld $04,y 1914 ld(hi('orw'),Y) #10,12
|
|
03fb e091 jmp y,$91 1915 jmp(Y,'orw') #11
|
|
1916 #dummy() #12 Overlap
|
|
1917 #
|
|
1918 # Instruction XORW: Word logical-XOR with zero page (vAC^=[D]+256*[D+1]), 26 cycles
|
|
1919 label('XORW')
|
|
XORW: 03fc 1404 ld $04,y 1920 ld(hi('xorw'),Y) #10,12
|
|
03fd e09c jmp y,$9c 1921 jmp(Y,'xorw') #11
|
|
03fe c21d st [$1d] 1922 st([vTmp]) #12
|
|
1923 # We keep XORW 2 cycles faster than ANDW/ORW, because that
|
|
1924 # can be useful for comparing numbers for equality a tiny
|
|
1925 # bit faster than with SUBW
|
|
1926
|
|
1927 # Instruction RET: Function return (vPC=vLR-2), 16 cycles
|
|
1928 label('RET')
|
|
RET: 03ff 011a ld [$1a] 1929 ld([vLR]) #10
|
|
1930 assert pc()&255 == 0
|
|
1931
|
|
1932 #-----------------------------------------------------------------------
|
|
1933 #
|
|
1934 # $0400 ROM page 4: Application interpreter extension
|
|
1935 #
|
|
1936 #-----------------------------------------------------------------------
|
|
1937 align(0x100, size=0x100)
|
|
1938
|
|
1939 # (Continue RET)
|
|
0400 a002 suba $02 1940 suba(2) #11
|
|
0401 c216 st [$16] 1941 st([vPC]) #12
|
|
0402 011b ld [$1b] 1942 ld([vLR+1]) #13
|
|
0403 c217 st [$17] 1943 st([vPC+1]) #14
|
|
0404 1403 ld $03,y 1944 ld(hi('REENTER'),Y) #15
|
|
0405 e0cb jmp y,$cb 1945 jmp(Y,'REENTER') #16
|
|
0406 00f6 ld $f6 1946 ld(-20/2) #17
|
|
1947
|
|
1948 # DEF implementation
|
|
1949 label('def#13')
|
|
def#13: 0407 0116 ld [$16] 1950 ld([vPC]) #13
|
|
0408 8002 adda $02 1951 adda(2) #14
|
|
0409 c218 st [$18] 1952 st([vAC]) #15
|
|
040a 0117 ld [$17] 1953 ld([vPC+1]) #16
|
|
040b c219 st [$19] 1954 st([vAC+1]) #17
|
|
040c 011d ld [$1d] 1955 ld([vTmp]) #18
|
|
040d c216 st [$16] 1956 st([vPC]) #19
|
|
040e 1403 ld $03,y 1957 ld(hi('NEXTY'),Y) #20
|
|
040f e000 jmp y,$00 1958 jmp(Y,'NEXTY') #21
|
|
0410 00f4 ld $f4 1959 ld(-24/2) #22
|
|
1960
|
|
1961 # Clear vACH (continuation of ANDI and LD instructions)
|
|
1962 label('andi#13')
|
|
andi#13: 0411 0200 nop 1963 nop() #13
|
|
0412 c218 st [$18] 1964 st([vAC]) #14
|
|
1965 #
|
|
1966 label('ld#15')
|
|
ld#15: 0413 0000 ld $00 1967 ld(0) #15 Clear high byte
|
|
0414 c219 st [$19] 1968 st([vAC+1]) #16
|
|
0415 1403 ld $03,y 1969 ld(hi('REENTER'),Y) #17
|
|
0416 e0cb jmp y,$cb 1970 jmp(Y,'REENTER') #18
|
|
0417 00f5 ld $f5 1971 ld(-22/2) #19
|
|
1972
|
|
1973 # ADDI implementation
|
|
1974 label('addi')
|
|
addi: 0418 8118 adda [$18] 1975 adda([vAC]) #13
|
|
0419 c218 st [$18] 1976 st([vAC]) #14 Store low result
|
|
041a e81e blt .addi#17 1977 bmi('.addi#17') #15 Now figure out if there was a carry
|
|
041b a11d suba [$1d] 1978 suba([vTmp]) #16 Gets back the initial value of vAC
|
|
041c fc20 bra .addi#19 1979 bra('.addi#19') #17
|
|
041d 411d ora [$1d] 1980 ora([vTmp]) #18 Carry in bit 7
|
|
1981 label('.addi#17')
|
|
.addi#17: 041e 211d anda [$1d] 1982 anda([vTmp]) #17 Carry in bit 7
|
|
041f 0200 nop 1983 nop() #18
|
|
1984 label('.addi#19')
|
|
.addi#19: 0420 3080 anda $80,x 1985 anda(0x80,X) #19 Move carry to bit 0
|
|
0421 0500 ld [x] 1986 ld([X]) #20
|
|
0422 8119 adda [$19] 1987 adda([vAC+1]) #21 Add the high bytes with carry
|
|
0423 1403 ld $03,y 1988 ld(hi('REENTER_28'),Y) #22
|
|
0424 e0ca jmp y,$ca 1989 jmp(Y,'REENTER_28') #23
|
|
0425 c219 st [$19] 1990 st([vAC+1]) #24 Store high result
|
|
1991
|
|
1992 # SUBI implementation
|
|
1993 label('subi')
|
|
subi: 0426 0118 ld [$18] 1994 ld([vAC]) #13
|
|
0427 e82c blt .subi#16 1995 bmi('.subi#16') #14
|
|
0428 a11d suba [$1d] 1996 suba([vTmp]) #15
|
|
0429 c218 st [$18] 1997 st([vAC]) #16 Store low result
|
|
042a fc2f bra .subi#19 1998 bra('.subi#19') #17
|
|
042b 411d ora [$1d] 1999 ora([vTmp]) #18 Carry in bit 7
|
|
2000 label('.subi#16')
|
|
.subi#16: 042c c218 st [$18] 2001 st([vAC]) #16 Store low result
|
|
042d 211d anda [$1d] 2002 anda([vTmp]) #17 Carry in bit 7
|
|
042e 0200 nop 2003 nop() #18
|
|
2004 label('.subi#19')
|
|
.subi#19: 042f 3080 anda $80,x 2005 anda(0x80,X) #19 Move carry to bit 0
|
|
0430 0119 ld [$19] 2006 ld([vAC+1]) #20
|
|
0431 a500 suba [x] 2007 suba([X]) #21
|
|
0432 1403 ld $03,y 2008 ld(hi('REENTER_28'),Y) #22
|
|
0433 e0ca jmp y,$ca 2009 jmp(Y,'REENTER_28') #23
|
|
0434 c219 st [$19] 2010 st([vAC+1]) #24
|
|
2011
|
|
2012 # LSLW implementation
|
|
2013 label('lslw')
|
|
lslw: 0435 3080 anda $80,x 2014 anda(128,X) #13
|
|
0436 8118 adda [$18] 2015 adda([vAC]) #14
|
|
0437 c218 st [$18] 2016 st([vAC]) #15
|
|
0438 0500 ld [x] 2017 ld([X]) #16
|
|
0439 8119 adda [$19] 2018 adda([vAC+1]) #17
|
|
043a 8119 adda [$19] 2019 adda([vAC+1]) #18
|
|
043b c219 st [$19] 2020 st([vAC+1]) #19
|
|
043c 0116 ld [$16] 2021 ld([vPC]) #20
|
|
043d a001 suba $01 2022 suba(1) #21
|
|
043e 1403 ld $03,y 2023 ld(hi('REENTER_28'),Y) #22
|
|
043f e0ca jmp y,$ca 2024 jmp(Y,'REENTER_28') #23
|
|
0440 c216 st [$16] 2025 st([vPC]) #24
|
|
2026
|
|
2027 # STLW implementation
|
|
2028 label('stlw')
|
|
stlw: 0441 811c adda [$1c] 2029 adda([vSP]) #13
|
|
0442 c21d st [$1d] 2030 st([vTmp]) #14
|
|
0443 9001 adda $01,x 2031 adda(1,X) #15
|
|
0444 0119 ld [$19] 2032 ld([vAC+1]) #16
|
|
0445 c600 st [x] 2033 st([X]) #17
|
|
0446 111d ld [$1d],x 2034 ld([vTmp],X) #18
|
|
0447 0118 ld [$18] 2035 ld([vAC]) #19
|
|
0448 c600 st [x] 2036 st([X]) #20
|
|
0449 1403 ld $03,y 2037 ld(hi('REENTER'),Y) #21
|
|
044a e0cb jmp y,$cb 2038 jmp(Y,'REENTER') #22
|
|
044b 00f3 ld $f3 2039 ld(-26/2) #23
|
|
2040
|
|
2041 # LDLW implementation
|
|
2042 label('ldlw')
|
|
ldlw: 044c 811c adda [$1c] 2043 adda([vSP]) #13
|
|
044d c21d st [$1d] 2044 st([vTmp]) #14
|
|
044e 9001 adda $01,x 2045 adda(1,X) #15
|
|
044f 0500 ld [x] 2046 ld([X]) #16
|
|
0450 c219 st [$19] 2047 st([vAC+1]) #17
|
|
0451 111d ld [$1d],x 2048 ld([vTmp],X) #18
|
|
0452 0500 ld [x] 2049 ld([X]) #19
|
|
0453 c218 st [$18] 2050 st([vAC]) #20
|
|
0454 1403 ld $03,y 2051 ld(hi('REENTER'),Y) #21
|
|
0455 e0cb jmp y,$cb 2052 jmp(Y,'REENTER') #22
|
|
0456 00f3 ld $f3 2053 ld(-26/2) #23
|
|
2054
|
|
2055 # POKE implementation
|
|
2056 label('poke')
|
|
poke: 0457 9001 adda $01,x 2057 adda(1,X) #13
|
|
0458 0500 ld [x] 2058 ld([X]) #14
|
|
0459 1600 ld ac,y 2059 ld(AC,Y) #15
|
|
045a 111d ld [$1d],x 2060 ld([vTmp],X) #16
|
|
045b 0500 ld [x] 2061 ld([X]) #17
|
|
045c 1200 ld ac,x 2062 ld(AC,X) #18
|
|
045d 0118 ld [$18] 2063 ld([vAC]) #19
|
|
045e ce00 st [y,x] 2064 st([Y,X]) #20
|
|
045f 1403 ld $03,y 2065 ld(hi('REENTER'),Y) #21
|
|
0460 e0cb jmp y,$cb 2066 jmp(Y,'REENTER') #22
|
|
0461 00f3 ld $f3 2067 ld(-26/2) #23
|
|
2068
|
|
2069 # PEEK implementation
|
|
2070 label('peek')
|
|
peek: 0462 a001 suba $01 2071 suba(1) #13
|
|
0463 c216 st [$16] 2072 st([vPC]) #14
|
|
0464 1118 ld [$18],x 2073 ld([vAC],X) #15
|
|
0465 1519 ld [$19],y 2074 ld([vAC+1],Y) #16
|
|
0466 0d00 ld [y,x] 2075 ld([Y,X]) #17
|
|
0467 c218 st [$18] 2076 st([vAC]) #18
|
|
2077 label('lupReturn#19') #Nice coincidence that lupReturn can be here
|
|
lupReturn#19: 0468 0000 ld $00 2078 ld(0) #19
|
|
0469 c219 st [$19] 2079 st([vAC+1]) #20
|
|
046a 1403 ld $03,y 2080 ld(hi('REENTER'),Y) #21
|
|
046b e0cb jmp y,$cb 2081 jmp(Y,'REENTER') #22
|
|
046c 00f3 ld $f3 2082 ld(-26/2) #23
|
|
2083
|
|
2084 # DOKE implementation
|
|
2085 label('doke')
|
|
doke: 046d 9001 adda $01,x 2086 adda(1,X) #13
|
|
046e 0500 ld [x] 2087 ld([X]) #14
|
|
046f 1600 ld ac,y 2088 ld(AC,Y) #15
|
|
0470 111d ld [$1d],x 2089 ld([vTmp],X) #16
|
|
0471 0500 ld [x] 2090 ld([X]) #17
|
|
0472 1200 ld ac,x 2091 ld(AC,X) #18
|
|
0473 0118 ld [$18] 2092 ld([vAC]) #19
|
|
0474 de00 st [y,x++] 2093 st([Y,Xpp]) #20
|
|
0475 0119 ld [$19] 2094 ld([vAC+1]) #21
|
|
0476 ce00 st [y,x] 2095 st([Y,X]) #22 Incompatible with REENTER_28
|
|
0477 1403 ld $03,y 2096 ld(hi('REENTER'),Y) #23
|
|
0478 e0cb jmp y,$cb 2097 jmp(Y,'REENTER') #24
|
|
0479 00f2 ld $f2 2098 ld(-28/2) #25
|
|
2099
|
|
2100 # DEEK implementation
|
|
2101 label('deek')
|
|
deek: 047a 0116 ld [$16] 2102 ld([vPC]) #13
|
|
047b a001 suba $01 2103 suba(1) #14
|
|
047c c216 st [$16] 2104 st([vPC]) #15
|
|
047d 1118 ld [$18],x 2105 ld([vAC],X) #16
|
|
047e 1519 ld [$19],y 2106 ld([vAC+1],Y) #17
|
|
047f 0d00 ld [y,x] 2107 ld([Y,X]) #18
|
|
0480 de00 st [y,x++] 2108 st([Y,Xpp]) #19 Just X++
|
|
0481 c218 st [$18] 2109 st([vAC]) #20
|
|
0482 0d00 ld [y,x] 2110 ld([Y,X]) #21
|
|
0483 1403 ld $03,y 2111 ld(hi('REENTER_28'),Y) #22
|
|
0484 e0ca jmp y,$ca 2112 jmp(Y,'REENTER_28') #23
|
|
0485 c219 st [$19] 2113 st([vAC+1]) #24
|
|
2114
|
|
2115 # ANDW implementation
|
|
2116 label('andw')
|
|
andw: 0486 c21d st [$1d] 2117 st([vTmp]) #13
|
|
0487 9001 adda $01,x 2118 adda(1,X) #14
|
|
0488 0500 ld [x] 2119 ld([X]) #15
|
|
0489 2119 anda [$19] 2120 anda([vAC+1]) #16
|
|
048a c219 st [$19] 2121 st([vAC+1]) #17
|
|
048b 111d ld [$1d],x 2122 ld([vTmp],X) #18
|
|
048c 0500 ld [x] 2123 ld([X]) #19
|
|
048d 2118 anda [$18] 2124 anda([vAC]) #20
|
|
048e c218 st [$18] 2125 st([vAC]) #21
|
|
048f 1403 ld $03,y 2126 ld(hi('REENTER_28'),Y) #22
|
|
0490 e0ca jmp y,$ca 2127 jmp(Y,'REENTER_28') #23
|
|
2128 #dummy() #24 Overlap
|
|
2129 #
|
|
2130 # ORW implementation
|
|
2131 label('orw')
|
|
orw: 0491 c21d st [$1d] 2132 st([vTmp]) #13,24
|
|
0492 9001 adda $01,x 2133 adda(1,X) #14
|
|
0493 0500 ld [x] 2134 ld([X]) #15
|
|
0494 4119 ora [$19] 2135 ora([vAC+1]) #16
|
|
0495 c219 st [$19] 2136 st([vAC+1]) #17
|
|
0496 111d ld [$1d],x 2137 ld([vTmp],X) #18
|
|
0497 0500 ld [x] 2138 ld([X]) #19
|
|
0498 4118 ora [$18] 2139 ora([vAC]) #20
|
|
0499 c218 st [$18] 2140 st([vAC]) #21
|
|
049a 1403 ld $03,y 2141 ld(hi('REENTER_28'),Y) #22
|
|
049b e0ca jmp y,$ca 2142 jmp(Y,'REENTER_28') #23
|
|
2143 #dummy() #24 Overlap
|
|
2144 #
|
|
2145 # XORW implementation
|
|
2146 label('xorw')
|
|
xorw: 049c 9001 adda $01,x 2147 adda(1,X) #13,24
|
|
049d 0500 ld [x] 2148 ld([X]) #14
|
|
049e 6119 xora [$19] 2149 xora([vAC+1]) #15
|
|
049f c219 st [$19] 2150 st([vAC+1]) #16
|
|
04a0 111d ld [$1d],x 2151 ld([vTmp],X) #17
|
|
04a1 0500 ld [x] 2152 ld([X]) #18
|
|
04a2 6118 xora [$18] 2153 xora([vAC]) #19
|
|
04a3 c218 st [$18] 2154 st([vAC]) #20
|
|
04a4 1403 ld $03,y 2155 ld(hi('REENTER'),Y) #21
|
|
04a5 e0cb jmp y,$cb 2156 jmp(Y,'REENTER') #22
|
|
04a6 00f3 ld $f3 2157 ld(-26/2) #23
|
|
2158
|
|
2159 #-----------------------------------------------------------------------
|
|
2160 #
|
|
2161 # vCPU extension functions (for acceleration and compaction) follow below.
|
|
2162 #
|
|
2163 # The naming convention is: SYS_<CamelCase>[_v<V>]_<N>
|
|
2164 #
|
|
2165 # With <N> the maximum number of cycles the function will run
|
|
2166 # (counted from NEXT to NEXT). This is the same number that must
|
|
2167 # be passed to the 'SYS' vCPU instruction as operand, and it will
|
|
2168 # appear in the GCL code upon use.
|
|
2169 #
|
|
2170 # If a SYS extension got introduced after ROM v1, the version number of
|
|
2171 # introduction is included in the name. This helps the programmer to be
|
|
2172 # reminded to verify the acutal ROM version and fail gracefully on older
|
|
2173 # ROMs than required. See also Docs/GT1-files.txt on using [romType].
|
|
2174 #
|
|
2175 #-----------------------------------------------------------------------
|
|
2176
|
|
2177 #-----------------------------------------------------------------------
|
|
2178 # Extension SYS_Random_34: Update entropy and copy to vAC
|
|
2179 #-----------------------------------------------------------------------
|
|
2180
|
|
2181 # This same algorithm runs automatically once per vertical blank.
|
|
2182 # Use this function to get numbers at a higher rate.
|
|
2183 #
|
|
2184 # Variables:
|
|
2185 # vAC
|
|
2186
|
|
2187 label('SYS_Random_34')
|
|
SYS_Random_34:
|
|
04a7 010e ld [$0e] 2188 ld([frameCount]) #15
|
|
04a8 6107 xora [$07] 2189 xora([entropy+1]) #16
|
|
04a9 610f xora [$0f] 2190 xora([serialRaw]) #17
|
|
04aa 8106 adda [$06] 2191 adda([entropy+0]) #18
|
|
04ab c206 st [$06] 2192 st([entropy+0]) #19
|
|
04ac c218 st [$18] 2193 st([vAC+0]) #20
|
|
04ad 8108 adda [$08] 2194 adda([entropy+2]) #21
|
|
04ae c208 st [$08] 2195 st([entropy+2]) #22
|
|
04af e8b2 blt .sysRnd0 2196 bmi('.sysRnd0') #23
|
|
04b0 fcb3 bra .sysRnd1 2197 bra('.sysRnd1') #24
|
|
04b1 6053 xora $53 2198 xora(64+16+2+1) #25
|
|
2199 label('.sysRnd0')
|
|
.sysRnd0: 04b2 606c xora $6c 2200 xora(64+32+8+4) #25
|
|
2201 label('.sysRnd1')
|
|
.sysRnd1: 04b3 8107 adda [$07] 2202 adda([entropy+1]) #26
|
|
04b4 c207 st [$07] 2203 st([entropy+1]) #27
|
|
04b5 c219 st [$19] 2204 st([vAC+1]) #28
|
|
04b6 1403 ld $03,y 2205 ld(hi('REENTER'),Y) #29
|
|
04b7 e0cb jmp y,$cb 2206 jmp(Y,'REENTER') #30
|
|
04b8 00ef ld $ef 2207 ld(-34/2) #31
|
|
2208
|
|
2209 label('SYS_LSRW7_30')
|
|
SYS_LSRW7_30: 04b9 0118 ld [$18] 2210 ld([vAC]) #15
|
|
04ba 3080 anda $80,x 2211 anda(128,X) #16
|
|
04bb 0119 ld [$19] 2212 ld([vAC+1]) #17
|
|
04bc 8200 adda ac 2213 adda(AC) #18
|
|
04bd 4500 ora [x] 2214 ora([X]) #19
|
|
04be c218 st [$18] 2215 st([vAC]) #20
|
|
04bf 0119 ld [$19] 2216 ld([vAC+1]) #21
|
|
04c0 3080 anda $80,x 2217 anda(128,X) #22
|
|
04c1 0500 ld [x] 2218 ld([X]) #23
|
|
04c2 c219 st [$19] 2219 st([vAC+1]) #24
|
|
04c3 1403 ld $03,y 2220 ld(hi('REENTER'),Y) #25
|
|
04c4 e0cb jmp y,$cb 2221 jmp(Y,'REENTER') #26
|
|
04c5 00f1 ld $f1 2222 ld(-30/2) #27
|
|
2223
|
|
2224 label('SYS_LSRW8_24')
|
|
SYS_LSRW8_24: 04c6 0119 ld [$19] 2225 ld([vAC+1]) #15
|
|
04c7 c218 st [$18] 2226 st([vAC]) #16
|
|
04c8 0000 ld $00 2227 ld(0) #17
|
|
04c9 c219 st [$19] 2228 st([vAC+1]) #18
|
|
04ca 1403 ld $03,y 2229 ld(hi('REENTER'),Y) #19
|
|
04cb e0cb jmp y,$cb 2230 jmp(Y,'REENTER') #20
|
|
04cc 00f4 ld $f4 2231 ld(-24/2) #21
|
|
2232
|
|
2233 label('SYS_LSLW8_24')
|
|
SYS_LSLW8_24: 04cd 0118 ld [$18] 2234 ld([vAC]) #15
|
|
04ce c219 st [$19] 2235 st([vAC+1]) #16
|
|
04cf 0000 ld $00 2236 ld(0) #17
|
|
04d0 c218 st [$18] 2237 st([vAC]) #18
|
|
04d1 1403 ld $03,y 2238 ld(hi('REENTER'),Y) #19
|
|
04d2 e0cb jmp y,$cb 2239 jmp(Y,'REENTER') #20
|
|
04d3 00f4 ld $f4 2240 ld(-24/2) #21
|
|
2241
|
|
2242 #-----------------------------------------------------------------------
|
|
2243 # Extension SYS_Draw4_30
|
|
2244 #-----------------------------------------------------------------------
|
|
2245
|
|
2246 # Draw 4 pixels on screen, horizontally next to each other
|
|
2247 #
|
|
2248 # Variables:
|
|
2249 # sysArgs[0:3] Pixels (in)
|
|
2250 # sysArgs[4:5] Position on screen (in)
|
|
2251
|
|
2252 label('SYS_Draw4_30')
|
|
SYS_Draw4_30: 04d4 1128 ld [$28],x 2253 ld([sysArgs+4],X) #15
|
|
04d5 1529 ld [$29],y 2254 ld([sysArgs+5],Y) #16
|
|
04d6 0124 ld [$24] 2255 ld([sysArgs+0]) #17
|
|
04d7 de00 st [y,x++] 2256 st([Y,Xpp]) #18
|
|
04d8 0125 ld [$25] 2257 ld([sysArgs+1]) #19
|
|
04d9 de00 st [y,x++] 2258 st([Y,Xpp]) #20
|
|
04da 0126 ld [$26] 2259 ld([sysArgs+2]) #21
|
|
04db de00 st [y,x++] 2260 st([Y,Xpp]) #22
|
|
04dc 0127 ld [$27] 2261 ld([sysArgs+3]) #23
|
|
04dd de00 st [y,x++] 2262 st([Y,Xpp]) #24
|
|
04de 1403 ld $03,y 2263 ld(hi('REENTER'),Y) #25
|
|
04df e0cb jmp y,$cb 2264 jmp(Y,'REENTER') #26
|
|
04e0 00f1 ld $f1 2265 ld(-30/2) #27
|
|
2266
|
|
2267 #-----------------------------------------------------------------------
|
|
2268 # Extension SYS_VDrawBits_134:
|
|
2269 #-----------------------------------------------------------------------
|
|
2270
|
|
2271 # Draw slice of a character, 8 pixels vertical
|
|
2272 #
|
|
2273 # Variables:
|
|
2274 # sysArgs[0] Color 0 "background" (in)
|
|
2275 # sysArgs[1] Color 1 "pen" (in)
|
|
2276 # sysArgs[2] 8 bits, highest bit first (in, changed)
|
|
2277 # sysArgs[4:5] Position on screen (in)
|
|
2278
|
|
2279 label('SYS_VDrawBits_134')
|
|
SYS_VDrawBits_134:
|
|
04e1 1412 ld $12,y 2280 ld(hi('sys_VDrawBits'),Y) #15
|
|
04e2 e08f jmp y,$8f 2281 jmp(Y,'sys_VDrawBits') #16
|
|
04e3 1128 ld [$28],x 2282 ld([sysArgs+4],X) #17
|
|
2283
|
|
2284 #-----------------------------------------------------------------------
|
|
2285
|
|
2286 # INC implementation
|
|
2287 label('inc#14')
|
|
inc#14: 04e4 8500 adda [x] 2288 adda([X]) #14
|
|
04e5 c600 st [x] 2289 st([X]) #15
|
|
04e6 1403 ld $03,y 2290 ld(hi('NEXTY'),Y) #16
|
|
04e7 e000 jmp y,$00 2291 jmp(Y,'NEXTY') #17
|
|
04e8 00f6 ld $f6 2292 ld(-20/2) #18
|
|
2293
|
|
2294 # Interrupt handler:
|
|
2295 # ST $xx -> optionally store vCpuSelect
|
|
2296 # ... IRQ payload ...
|
|
2297 # either:
|
|
2298 # LDWI $400
|
|
2299 # LUP 0 -> vRTI and don't switch interpreter (immediate resume)
|
|
2300 # or:
|
|
2301 # LDWI $400
|
|
2302 # LUP $xx -> vRTI and switch interpreter type as stored in [$xx]
|
|
04e9 0200 nop 2303 fillers(until=251-11)
|
|
04ea 0200 nop
|
|
04eb 0200 nop
|
|
* 7 times
|
|
2304 label('vRTI#15')
|
|
vRTI#15: 04f0 0130 ld [$30] 2305 ld([0x30]) #15 Continue with vCPU in the same timeslice (faster)
|
|
04f1 c216 st [$16] 2306 st([vPC]) #16
|
|
04f2 0131 ld [$31] 2307 ld([0x31]) #17
|
|
04f3 c217 st [$17] 2308 st([vPC+1]) #18
|
|
04f4 0132 ld [$32] 2309 ld([0x32]) #19
|
|
04f5 c218 st [$18] 2310 st([vAC]) #20
|
|
04f6 0133 ld [$33] 2311 ld([0x33]) #21
|
|
04f7 c219 st [$19] 2312 st([vAC+1]) #22
|
|
04f8 1403 ld $03,y 2313 ld(hi('REENTER'),Y) #23
|
|
04f9 e0cb jmp y,$cb 2314 jmp(Y,'REENTER') #24
|
|
04fa 00f2 ld $f2 2315 ld(-28/2) #25
|
|
2316 # vRTI entry point
|
|
2317 assert(pc()&255 == 251) # The landing offset 251 for LUP trampoline is fixed
|
|
04fb f0f0 beq vRTI#15 2318 beq('vRTI#15') #13 vRTI sequence
|
|
04fc 9001 adda $01,x 2319 adda(1,X) #14
|
|
04fd 1412 ld $12,y 2320 ld(hi('vRTI#18'),Y) #15 Switch and wait for end of timeslice (slower)
|
|
04fe e020 jmp y,$20 2321 jmp(Y,'vRTI#18') #16
|
|
04ff c21d st [$1d] 2322 st([vTmp]) #17
|
|
2323
|
|
2324 #-----------------------------------------------------------------------
|
|
2325 #
|
|
2326 # $0500 ROM page 5-6: Shift table and code
|
|
2327 #
|
|
2328 #-----------------------------------------------------------------------
|
|
2329
|
|
2330 align(0x100, size=0x200)
|
|
2331
|
|
2332 # Lookup table for i>>n, with n in 1..6
|
|
2333 # Indexing ix = i & ~b | (b-1), where b = 1<<(n-1)
|
|
2334 # ...
|
|
2335 # ld <.ret
|
|
2336 # st [vTmp]
|
|
2337 # ld >shiftTable,y
|
|
2338 # <calculate ix>
|
|
2339 # jmp y,ac
|
|
2340 # bra $ff
|
|
2341 # .ret: ...
|
|
2342 #
|
|
2343 # i >> 7 can be always be done with RAM: [i&128]
|
|
2344 # ...
|
|
2345 # anda $80,x
|
|
2346 # ld [x]
|
|
2347 # ...
|
|
2348
|
|
2349 label('shiftTable')
|
|
2350 shiftTable = pc()
|
|
2351
|
|
2352 for ix in range(255):
|
|
2353 for n in range(1,7): # Find first zero
|
|
2354 if ~ix & (1 << (n-1)):
|
|
2355 break
|
|
2356 pattern = ['x' if i<n else '1' if ix&(1<<i) else '0' for i in range(8)]
|
|
2357 ld(ix>>n); C('0b%s >> %d' % (''.join(reversed(pattern)), n))
|
|
shiftTable: 0500 0000 ld $00 ;0b0000000x >> 1
|
|
0501 0000 ld $00 ;0b000000xx >> 2
|
|
0502 0001 ld $01 ;0b0000001x >> 1
|
|
0503 0000 ld $00 ;0b00000xxx >> 3
|
|
0504 0002 ld $02 ;0b0000010x >> 1
|
|
0505 0001 ld $01 ;0b000001xx >> 2
|
|
0506 0003 ld $03 ;0b0000011x >> 1
|
|
0507 0000 ld $00 ;0b0000xxxx >> 4
|
|
0508 0004 ld $04 ;0b0000100x >> 1
|
|
0509 0002 ld $02 ;0b000010xx >> 2
|
|
050a 0005 ld $05 ;0b0000101x >> 1
|
|
050b 0001 ld $01 ;0b00001xxx >> 3
|
|
050c 0006 ld $06 ;0b0000110x >> 1
|
|
050d 0003 ld $03 ;0b000011xx >> 2
|
|
050e 0007 ld $07 ;0b0000111x >> 1
|
|
050f 0000 ld $00 ;0b000xxxxx >> 5
|
|
0510 0008 ld $08 ;0b0001000x >> 1
|
|
0511 0004 ld $04 ;0b000100xx >> 2
|
|
0512 0009 ld $09 ;0b0001001x >> 1
|
|
0513 0002 ld $02 ;0b00010xxx >> 3
|
|
0514 000a ld $0a ;0b0001010x >> 1
|
|
0515 0005 ld $05 ;0b000101xx >> 2
|
|
0516 000b ld $0b ;0b0001011x >> 1
|
|
0517 0001 ld $01 ;0b0001xxxx >> 4
|
|
0518 000c ld $0c ;0b0001100x >> 1
|
|
0519 0006 ld $06 ;0b000110xx >> 2
|
|
051a 000d ld $0d ;0b0001101x >> 1
|
|
051b 0003 ld $03 ;0b00011xxx >> 3
|
|
051c 000e ld $0e ;0b0001110x >> 1
|
|
051d 0007 ld $07 ;0b000111xx >> 2
|
|
051e 000f ld $0f ;0b0001111x >> 1
|
|
051f 0000 ld $00 ;0b00xxxxxx >> 6
|
|
0520 0010 ld $10 ;0b0010000x >> 1
|
|
0521 0008 ld $08 ;0b001000xx >> 2
|
|
0522 0011 ld $11 ;0b0010001x >> 1
|
|
0523 0004 ld $04 ;0b00100xxx >> 3
|
|
0524 0012 ld $12 ;0b0010010x >> 1
|
|
0525 0009 ld $09 ;0b001001xx >> 2
|
|
0526 0013 ld $13 ;0b0010011x >> 1
|
|
0527 0002 ld $02 ;0b0010xxxx >> 4
|
|
0528 0014 ld $14 ;0b0010100x >> 1
|
|
0529 000a ld $0a ;0b001010xx >> 2
|
|
052a 0015 ld $15 ;0b0010101x >> 1
|
|
052b 0005 ld $05 ;0b00101xxx >> 3
|
|
052c 0016 ld $16 ;0b0010110x >> 1
|
|
052d 000b ld $0b ;0b001011xx >> 2
|
|
052e 0017 ld $17 ;0b0010111x >> 1
|
|
052f 0001 ld $01 ;0b001xxxxx >> 5
|
|
0530 0018 ld $18 ;0b0011000x >> 1
|
|
0531 000c ld $0c ;0b001100xx >> 2
|
|
0532 0019 ld $19 ;0b0011001x >> 1
|
|
0533 0006 ld $06 ;0b00110xxx >> 3
|
|
0534 001a ld $1a ;0b0011010x >> 1
|
|
0535 000d ld $0d ;0b001101xx >> 2
|
|
0536 001b ld $1b ;0b0011011x >> 1
|
|
0537 0003 ld $03 ;0b0011xxxx >> 4
|
|
0538 001c ld $1c ;0b0011100x >> 1
|
|
0539 000e ld $0e ;0b001110xx >> 2
|
|
053a 001d ld $1d ;0b0011101x >> 1
|
|
053b 0007 ld $07 ;0b00111xxx >> 3
|
|
053c 001e ld $1e ;0b0011110x >> 1
|
|
053d 000f ld $0f ;0b001111xx >> 2
|
|
053e 001f ld $1f ;0b0011111x >> 1
|
|
053f 0000 ld $00 ;0b00xxxxxx >> 6
|
|
0540 0020 ld $20 ;0b0100000x >> 1
|
|
0541 0010 ld $10 ;0b010000xx >> 2
|
|
0542 0021 ld $21 ;0b0100001x >> 1
|
|
0543 0008 ld $08 ;0b01000xxx >> 3
|
|
0544 0022 ld $22 ;0b0100010x >> 1
|
|
0545 0011 ld $11 ;0b010001xx >> 2
|
|
0546 0023 ld $23 ;0b0100011x >> 1
|
|
0547 0004 ld $04 ;0b0100xxxx >> 4
|
|
0548 0024 ld $24 ;0b0100100x >> 1
|
|
0549 0012 ld $12 ;0b010010xx >> 2
|
|
054a 0025 ld $25 ;0b0100101x >> 1
|
|
054b 0009 ld $09 ;0b01001xxx >> 3
|
|
054c 0026 ld $26 ;0b0100110x >> 1
|
|
054d 0013 ld $13 ;0b010011xx >> 2
|
|
054e 0027 ld $27 ;0b0100111x >> 1
|
|
054f 0002 ld $02 ;0b010xxxxx >> 5
|
|
0550 0028 ld $28 ;0b0101000x >> 1
|
|
0551 0014 ld $14 ;0b010100xx >> 2
|
|
0552 0029 ld $29 ;0b0101001x >> 1
|
|
0553 000a ld $0a ;0b01010xxx >> 3
|
|
0554 002a ld $2a ;0b0101010x >> 1
|
|
0555 0015 ld $15 ;0b010101xx >> 2
|
|
0556 002b ld $2b ;0b0101011x >> 1
|
|
0557 0005 ld $05 ;0b0101xxxx >> 4
|
|
0558 002c ld $2c ;0b0101100x >> 1
|
|
0559 0016 ld $16 ;0b010110xx >> 2
|
|
055a 002d ld $2d ;0b0101101x >> 1
|
|
055b 000b ld $0b ;0b01011xxx >> 3
|
|
055c 002e ld $2e ;0b0101110x >> 1
|
|
055d 0017 ld $17 ;0b010111xx >> 2
|
|
055e 002f ld $2f ;0b0101111x >> 1
|
|
055f 0001 ld $01 ;0b01xxxxxx >> 6
|
|
0560 0030 ld $30 ;0b0110000x >> 1
|
|
0561 0018 ld $18 ;0b011000xx >> 2
|
|
0562 0031 ld $31 ;0b0110001x >> 1
|
|
0563 000c ld $0c ;0b01100xxx >> 3
|
|
0564 0032 ld $32 ;0b0110010x >> 1
|
|
0565 0019 ld $19 ;0b011001xx >> 2
|
|
0566 0033 ld $33 ;0b0110011x >> 1
|
|
0567 0006 ld $06 ;0b0110xxxx >> 4
|
|
0568 0034 ld $34 ;0b0110100x >> 1
|
|
0569 001a ld $1a ;0b011010xx >> 2
|
|
056a 0035 ld $35 ;0b0110101x >> 1
|
|
056b 000d ld $0d ;0b01101xxx >> 3
|
|
056c 0036 ld $36 ;0b0110110x >> 1
|
|
056d 001b ld $1b ;0b011011xx >> 2
|
|
056e 0037 ld $37 ;0b0110111x >> 1
|
|
056f 0003 ld $03 ;0b011xxxxx >> 5
|
|
0570 0038 ld $38 ;0b0111000x >> 1
|
|
0571 001c ld $1c ;0b011100xx >> 2
|
|
0572 0039 ld $39 ;0b0111001x >> 1
|
|
0573 000e ld $0e ;0b01110xxx >> 3
|
|
0574 003a ld $3a ;0b0111010x >> 1
|
|
0575 001d ld $1d ;0b011101xx >> 2
|
|
0576 003b ld $3b ;0b0111011x >> 1
|
|
0577 0007 ld $07 ;0b0111xxxx >> 4
|
|
0578 003c ld $3c ;0b0111100x >> 1
|
|
0579 001e ld $1e ;0b011110xx >> 2
|
|
057a 003d ld $3d ;0b0111101x >> 1
|
|
057b 000f ld $0f ;0b01111xxx >> 3
|
|
057c 003e ld $3e ;0b0111110x >> 1
|
|
057d 001f ld $1f ;0b011111xx >> 2
|
|
057e 003f ld $3f ;0b0111111x >> 1
|
|
057f 0001 ld $01 ;0b01xxxxxx >> 6
|
|
0580 0040 ld $40 ;0b1000000x >> 1
|
|
0581 0020 ld $20 ;0b100000xx >> 2
|
|
0582 0041 ld $41 ;0b1000001x >> 1
|
|
0583 0010 ld $10 ;0b10000xxx >> 3
|
|
0584 0042 ld $42 ;0b1000010x >> 1
|
|
0585 0021 ld $21 ;0b100001xx >> 2
|
|
0586 0043 ld $43 ;0b1000011x >> 1
|
|
0587 0008 ld $08 ;0b1000xxxx >> 4
|
|
0588 0044 ld $44 ;0b1000100x >> 1
|
|
0589 0022 ld $22 ;0b100010xx >> 2
|
|
058a 0045 ld $45 ;0b1000101x >> 1
|
|
058b 0011 ld $11 ;0b10001xxx >> 3
|
|
058c 0046 ld $46 ;0b1000110x >> 1
|
|
058d 0023 ld $23 ;0b100011xx >> 2
|
|
058e 0047 ld $47 ;0b1000111x >> 1
|
|
058f 0004 ld $04 ;0b100xxxxx >> 5
|
|
0590 0048 ld $48 ;0b1001000x >> 1
|
|
0591 0024 ld $24 ;0b100100xx >> 2
|
|
0592 0049 ld $49 ;0b1001001x >> 1
|
|
0593 0012 ld $12 ;0b10010xxx >> 3
|
|
0594 004a ld $4a ;0b1001010x >> 1
|
|
0595 0025 ld $25 ;0b100101xx >> 2
|
|
0596 004b ld $4b ;0b1001011x >> 1
|
|
0597 0009 ld $09 ;0b1001xxxx >> 4
|
|
0598 004c ld $4c ;0b1001100x >> 1
|
|
0599 0026 ld $26 ;0b100110xx >> 2
|
|
059a 004d ld $4d ;0b1001101x >> 1
|
|
059b 0013 ld $13 ;0b10011xxx >> 3
|
|
059c 004e ld $4e ;0b1001110x >> 1
|
|
059d 0027 ld $27 ;0b100111xx >> 2
|
|
059e 004f ld $4f ;0b1001111x >> 1
|
|
059f 0002 ld $02 ;0b10xxxxxx >> 6
|
|
05a0 0050 ld $50 ;0b1010000x >> 1
|
|
05a1 0028 ld $28 ;0b101000xx >> 2
|
|
05a2 0051 ld $51 ;0b1010001x >> 1
|
|
05a3 0014 ld $14 ;0b10100xxx >> 3
|
|
05a4 0052 ld $52 ;0b1010010x >> 1
|
|
05a5 0029 ld $29 ;0b101001xx >> 2
|
|
05a6 0053 ld $53 ;0b1010011x >> 1
|
|
05a7 000a ld $0a ;0b1010xxxx >> 4
|
|
05a8 0054 ld $54 ;0b1010100x >> 1
|
|
05a9 002a ld $2a ;0b101010xx >> 2
|
|
05aa 0055 ld $55 ;0b1010101x >> 1
|
|
05ab 0015 ld $15 ;0b10101xxx >> 3
|
|
05ac 0056 ld $56 ;0b1010110x >> 1
|
|
05ad 002b ld $2b ;0b101011xx >> 2
|
|
05ae 0057 ld $57 ;0b1010111x >> 1
|
|
05af 0005 ld $05 ;0b101xxxxx >> 5
|
|
05b0 0058 ld $58 ;0b1011000x >> 1
|
|
05b1 002c ld $2c ;0b101100xx >> 2
|
|
05b2 0059 ld $59 ;0b1011001x >> 1
|
|
05b3 0016 ld $16 ;0b10110xxx >> 3
|
|
05b4 005a ld $5a ;0b1011010x >> 1
|
|
05b5 002d ld $2d ;0b101101xx >> 2
|
|
05b6 005b ld $5b ;0b1011011x >> 1
|
|
05b7 000b ld $0b ;0b1011xxxx >> 4
|
|
05b8 005c ld $5c ;0b1011100x >> 1
|
|
05b9 002e ld $2e ;0b101110xx >> 2
|
|
05ba 005d ld $5d ;0b1011101x >> 1
|
|
05bb 0017 ld $17 ;0b10111xxx >> 3
|
|
05bc 005e ld $5e ;0b1011110x >> 1
|
|
05bd 002f ld $2f ;0b101111xx >> 2
|
|
05be 005f ld $5f ;0b1011111x >> 1
|
|
05bf 0002 ld $02 ;0b10xxxxxx >> 6
|
|
05c0 0060 ld $60 ;0b1100000x >> 1
|
|
05c1 0030 ld $30 ;0b110000xx >> 2
|
|
05c2 0061 ld $61 ;0b1100001x >> 1
|
|
05c3 0018 ld $18 ;0b11000xxx >> 3
|
|
05c4 0062 ld $62 ;0b1100010x >> 1
|
|
05c5 0031 ld $31 ;0b110001xx >> 2
|
|
05c6 0063 ld $63 ;0b1100011x >> 1
|
|
05c7 000c ld $0c ;0b1100xxxx >> 4
|
|
05c8 0064 ld $64 ;0b1100100x >> 1
|
|
05c9 0032 ld $32 ;0b110010xx >> 2
|
|
05ca 0065 ld $65 ;0b1100101x >> 1
|
|
05cb 0019 ld $19 ;0b11001xxx >> 3
|
|
05cc 0066 ld $66 ;0b1100110x >> 1
|
|
05cd 0033 ld $33 ;0b110011xx >> 2
|
|
05ce 0067 ld $67 ;0b1100111x >> 1
|
|
05cf 0006 ld $06 ;0b110xxxxx >> 5
|
|
05d0 0068 ld $68 ;0b1101000x >> 1
|
|
05d1 0034 ld $34 ;0b110100xx >> 2
|
|
05d2 0069 ld $69 ;0b1101001x >> 1
|
|
05d3 001a ld $1a ;0b11010xxx >> 3
|
|
05d4 006a ld $6a ;0b1101010x >> 1
|
|
05d5 0035 ld $35 ;0b110101xx >> 2
|
|
05d6 006b ld $6b ;0b1101011x >> 1
|
|
05d7 000d ld $0d ;0b1101xxxx >> 4
|
|
05d8 006c ld $6c ;0b1101100x >> 1
|
|
05d9 0036 ld $36 ;0b110110xx >> 2
|
|
05da 006d ld $6d ;0b1101101x >> 1
|
|
05db 001b ld $1b ;0b11011xxx >> 3
|
|
05dc 006e ld $6e ;0b1101110x >> 1
|
|
05dd 0037 ld $37 ;0b110111xx >> 2
|
|
05de 006f ld $6f ;0b1101111x >> 1
|
|
05df 0003 ld $03 ;0b11xxxxxx >> 6
|
|
05e0 0070 ld $70 ;0b1110000x >> 1
|
|
05e1 0038 ld $38 ;0b111000xx >> 2
|
|
05e2 0071 ld $71 ;0b1110001x >> 1
|
|
05e3 001c ld $1c ;0b11100xxx >> 3
|
|
05e4 0072 ld $72 ;0b1110010x >> 1
|
|
05e5 0039 ld $39 ;0b111001xx >> 2
|
|
05e6 0073 ld $73 ;0b1110011x >> 1
|
|
05e7 000e ld $0e ;0b1110xxxx >> 4
|
|
05e8 0074 ld $74 ;0b1110100x >> 1
|
|
05e9 003a ld $3a ;0b111010xx >> 2
|
|
05ea 0075 ld $75 ;0b1110101x >> 1
|
|
05eb 001d ld $1d ;0b11101xxx >> 3
|
|
05ec 0076 ld $76 ;0b1110110x >> 1
|
|
05ed 003b ld $3b ;0b111011xx >> 2
|
|
05ee 0077 ld $77 ;0b1110111x >> 1
|
|
05ef 0007 ld $07 ;0b111xxxxx >> 5
|
|
05f0 0078 ld $78 ;0b1111000x >> 1
|
|
05f1 003c ld $3c ;0b111100xx >> 2
|
|
05f2 0079 ld $79 ;0b1111001x >> 1
|
|
05f3 001e ld $1e ;0b11110xxx >> 3
|
|
05f4 007a ld $7a ;0b1111010x >> 1
|
|
05f5 003d ld $3d ;0b111101xx >> 2
|
|
05f6 007b ld $7b ;0b1111011x >> 1
|
|
05f7 000f ld $0f ;0b1111xxxx >> 4
|
|
05f8 007c ld $7c ;0b1111100x >> 1
|
|
05f9 003e ld $3e ;0b111110xx >> 2
|
|
05fa 007d ld $7d ;0b1111101x >> 1
|
|
05fb 001f ld $1f ;0b11111xxx >> 3
|
|
05fc 007e ld $7e ;0b1111110x >> 1
|
|
05fd 003f ld $3f ;0b111111xx >> 2
|
|
05fe 007f ld $7f ;0b1111111x >> 1
|
|
2358
|
|
2359 assert pc()&255 == 255
|
|
05ff fd1d bra [$1d] 2360 bra([vTmp]) # Jumps back into next page
|
|
2361
|
|
2362 label('SYS_LSRW1_48')
|
|
2363 assert pc()&255 == 0 # First instruction on this page *must* be a nop
|
|
SYS_LSRW1_48: 0600 0200 nop 2364 nop() #15
|
|
0601 1405 ld $05,y 2365 ld(hi('shiftTable'),Y) #16 Logical shift right 1 bit (X >> 1)
|
|
0602 0008 ld $08 2366 ld('.sysLsrw1a') #17 Shift low byte
|
|
0603 c21d st [$1d] 2367 st([vTmp]) #18
|
|
0604 0118 ld [$18] 2368 ld([vAC]) #19
|
|
0605 20fe anda $fe 2369 anda(0b11111110) #20
|
|
0606 e200 jmp y,ac 2370 jmp(Y,AC) #21
|
|
0607 fcff bra $ff 2371 bra(255) #22 bra shiftTable+255
|
|
2372 label('.sysLsrw1a')
|
|
.sysLsrw1a: 0608 c218 st [$18] 2373 st([vAC]) #26
|
|
0609 0119 ld [$19] 2374 ld([vAC+1]) #27 Transfer bit 8
|
|
060a 2001 anda $01 2375 anda(1) #28
|
|
060b 807f adda $7f 2376 adda(127) #29
|
|
060c 2080 anda $80 2377 anda(128) #30
|
|
060d 4118 ora [$18] 2378 ora([vAC]) #31
|
|
060e c218 st [$18] 2379 st([vAC]) #32
|
|
060f 0015 ld $15 2380 ld('.sysLsrw1b') #33 Shift high byte
|
|
0610 c21d st [$1d] 2381 st([vTmp]) #34
|
|
0611 0119 ld [$19] 2382 ld([vAC+1]) #35
|
|
0612 20fe anda $fe 2383 anda(0b11111110) #36
|
|
0613 e200 jmp y,ac 2384 jmp(Y,AC) #37
|
|
0614 fcff bra $ff 2385 bra(255) #38 bra shiftTable+255
|
|
2386 label('.sysLsrw1b')
|
|
.sysLsrw1b: 0615 c219 st [$19] 2387 st([vAC+1]) #42
|
|
0616 1403 ld $03,y 2388 ld(hi('REENTER'),Y) #43
|
|
0617 e0cb jmp y,$cb 2389 jmp(Y,'REENTER') #44
|
|
0618 00e8 ld $e8 2390 ld(-48/2) #45
|
|
2391
|
|
2392 label('SYS_LSRW2_52')
|
|
SYS_LSRW2_52: 0619 1405 ld $05,y 2393 ld(hi('shiftTable'),Y) #15 Logical shift right 2 bit (X >> 2)
|
|
061a 0021 ld $21 2394 ld('.sysLsrw2a') #16 Shift low byte
|
|
061b c21d st [$1d] 2395 st([vTmp]) #17
|
|
061c 0118 ld [$18] 2396 ld([vAC]) #18
|
|
061d 20fc anda $fc 2397 anda(0b11111100) #19
|
|
061e 4001 ora $01 2398 ora( 0b00000001) #20
|
|
061f e200 jmp y,ac 2399 jmp(Y,AC) #21
|
|
0620 fcff bra $ff 2400 bra(255) #22 bra shiftTable+255
|
|
2401 label('.sysLsrw2a')
|
|
.sysLsrw2a: 0621 c218 st [$18] 2402 st([vAC]) #26
|
|
0622 0119 ld [$19] 2403 ld([vAC+1]) #27 Transfer bit 8:9
|
|
0623 8200 adda ac 2404 adda(AC) #28
|
|
0624 8200 adda ac 2405 adda(AC) #29
|
|
0625 8200 adda ac 2406 adda(AC) #30
|
|
0626 8200 adda ac 2407 adda(AC) #31
|
|
0627 8200 adda ac 2408 adda(AC) #32
|
|
0628 8200 adda ac 2409 adda(AC) #33
|
|
0629 4118 ora [$18] 2410 ora([vAC]) #34
|
|
062a c218 st [$18] 2411 st([vAC]) #35
|
|
062b 0032 ld $32 2412 ld('.sysLsrw2b') #36 Shift high byte
|
|
062c c21d st [$1d] 2413 st([vTmp]) #37
|
|
062d 0119 ld [$19] 2414 ld([vAC+1]) #38
|
|
062e 20fc anda $fc 2415 anda(0b11111100) #39
|
|
062f 4001 ora $01 2416 ora( 0b00000001) #40
|
|
0630 e200 jmp y,ac 2417 jmp(Y,AC) #41
|
|
0631 fcff bra $ff 2418 bra(255) #42 bra shiftTable+255
|
|
2419 label('.sysLsrw2b')
|
|
.sysLsrw2b: 0632 c219 st [$19] 2420 st([vAC+1]) #46
|
|
0633 1403 ld $03,y 2421 ld(hi('REENTER'),Y) #47
|
|
0634 e0cb jmp y,$cb 2422 jmp(Y,'REENTER') #48
|
|
0635 00e6 ld $e6 2423 ld(-52/2) #49
|
|
2424
|
|
2425 label('SYS_LSRW3_52')
|
|
SYS_LSRW3_52: 0636 1405 ld $05,y 2426 ld(hi('shiftTable'),Y) #15 Logical shift right 3 bit (X >> 3)
|
|
0637 003e ld $3e 2427 ld('.sysLsrw3a') #16 Shift low byte
|
|
0638 c21d st [$1d] 2428 st([vTmp]) #17
|
|
0639 0118 ld [$18] 2429 ld([vAC]) #18
|
|
063a 20f8 anda $f8 2430 anda(0b11111000) #19
|
|
063b 4003 ora $03 2431 ora( 0b00000011) #20
|
|
063c e200 jmp y,ac 2432 jmp(Y,AC) #21
|
|
063d fcff bra $ff 2433 bra(255) #22 bra shiftTable+255
|
|
2434 label('.sysLsrw3a')
|
|
.sysLsrw3a: 063e c218 st [$18] 2435 st([vAC]) #26
|
|
063f 0119 ld [$19] 2436 ld([vAC+1]) #27 Transfer bit 8:10
|
|
0640 8200 adda ac 2437 adda(AC) #28
|
|
0641 8200 adda ac 2438 adda(AC) #29
|
|
0642 8200 adda ac 2439 adda(AC) #30
|
|
0643 8200 adda ac 2440 adda(AC) #31
|
|
0644 8200 adda ac 2441 adda(AC) #32
|
|
0645 4118 ora [$18] 2442 ora([vAC]) #33
|
|
0646 c218 st [$18] 2443 st([vAC]) #34
|
|
0647 004e ld $4e 2444 ld('.sysLsrw3b') #35 Shift high byte
|
|
0648 c21d st [$1d] 2445 st([vTmp]) #36
|
|
0649 0119 ld [$19] 2446 ld([vAC+1]) #37
|
|
064a 20f8 anda $f8 2447 anda(0b11111000) #38
|
|
064b 4003 ora $03 2448 ora( 0b00000011) #39
|
|
064c e200 jmp y,ac 2449 jmp(Y,AC) #40
|
|
064d fcff bra $ff 2450 bra(255) #41 bra shiftTable+255
|
|
2451 label('.sysLsrw3b')
|
|
.sysLsrw3b: 064e c219 st [$19] 2452 st([vAC+1]) #45
|
|
064f 00e6 ld $e6 2453 ld(-52/2) #46
|
|
0650 1403 ld $03,y 2454 ld(hi('REENTER'),Y) #47
|
|
0651 e0cb jmp y,$cb 2455 jmp(Y,'REENTER') #48
|
|
2456 #nop() #49
|
|
2457
|
|
2458 label('SYS_LSRW4_50')
|
|
SYS_LSRW4_50: 0652 1405 ld $05,y 2459 ld(hi('shiftTable'),Y) #15,49 Logical shift right 4 bit (X >> 4)
|
|
0653 005a ld $5a 2460 ld('.sysLsrw4a') #16 Shift low byte
|
|
0654 c21d st [$1d] 2461 st([vTmp]) #17
|
|
0655 0118 ld [$18] 2462 ld([vAC]) #18
|
|
0656 20f0 anda $f0 2463 anda(0b11110000) #19
|
|
0657 4007 ora $07 2464 ora( 0b00000111) #20
|
|
0658 e200 jmp y,ac 2465 jmp(Y,AC) #21
|
|
0659 fcff bra $ff 2466 bra(255) #22 bra shiftTable+255
|
|
2467 label('.sysLsrw4a')
|
|
.sysLsrw4a: 065a c218 st [$18] 2468 st([vAC]) #26
|
|
065b 0119 ld [$19] 2469 ld([vAC+1]) #27 Transfer bit 8:11
|
|
065c 8200 adda ac 2470 adda(AC) #28
|
|
065d 8200 adda ac 2471 adda(AC) #29
|
|
065e 8200 adda ac 2472 adda(AC) #30
|
|
065f 8200 adda ac 2473 adda(AC) #31
|
|
0660 4118 ora [$18] 2474 ora([vAC]) #32
|
|
0661 c218 st [$18] 2475 st([vAC]) #33
|
|
0662 0069 ld $69 2476 ld('.sysLsrw4b') #34 Shift high byte'
|
|
0663 c21d st [$1d] 2477 st([vTmp]) #35
|
|
0664 0119 ld [$19] 2478 ld([vAC+1]) #36
|
|
0665 20f0 anda $f0 2479 anda(0b11110000) #37
|
|
0666 4007 ora $07 2480 ora( 0b00000111) #38
|
|
0667 e200 jmp y,ac 2481 jmp(Y,AC) #39
|
|
0668 fcff bra $ff 2482 bra(255) #40 bra shiftTable+255
|
|
2483 label('.sysLsrw4b')
|
|
.sysLsrw4b: 0669 c219 st [$19] 2484 st([vAC+1]) #44
|
|
066a 1403 ld $03,y 2485 ld(hi('REENTER'),Y) #45
|
|
066b e0cb jmp y,$cb 2486 jmp(Y,'REENTER') #46
|
|
066c 00e7 ld $e7 2487 ld(-50/2) #47
|
|
2488
|
|
2489 label('SYS_LSRW5_50')
|
|
SYS_LSRW5_50: 066d 1405 ld $05,y 2490 ld(hi('shiftTable'),Y) #15 Logical shift right 5 bit (X >> 5)
|
|
066e 0075 ld $75 2491 ld('.sysLsrw5a') #16 Shift low byte
|
|
066f c21d st [$1d] 2492 st([vTmp]) #17
|
|
0670 0118 ld [$18] 2493 ld([vAC]) #18
|
|
0671 20e0 anda $e0 2494 anda(0b11100000) #19
|
|
0672 400f ora $0f 2495 ora( 0b00001111) #20
|
|
0673 e200 jmp y,ac 2496 jmp(Y,AC) #21
|
|
0674 fcff bra $ff 2497 bra(255) #22 bra shiftTable+255
|
|
2498 label('.sysLsrw5a')
|
|
.sysLsrw5a: 0675 c218 st [$18] 2499 st([vAC]) #26
|
|
0676 0119 ld [$19] 2500 ld([vAC+1]) #27 Transfer bit 8:13
|
|
0677 8200 adda ac 2501 adda(AC) #28
|
|
0678 8200 adda ac 2502 adda(AC) #29
|
|
0679 8200 adda ac 2503 adda(AC) #30
|
|
067a 4118 ora [$18] 2504 ora([vAC]) #31
|
|
067b c218 st [$18] 2505 st([vAC]) #32
|
|
067c 0083 ld $83 2506 ld('.sysLsrw5b') #33 Shift high byte
|
|
067d c21d st [$1d] 2507 st([vTmp]) #34
|
|
067e 0119 ld [$19] 2508 ld([vAC+1]) #35
|
|
067f 20e0 anda $e0 2509 anda(0b11100000) #36
|
|
0680 400f ora $0f 2510 ora( 0b00001111) #37
|
|
0681 e200 jmp y,ac 2511 jmp(Y,AC) #38
|
|
0682 fcff bra $ff 2512 bra(255) #39 bra shiftTable+255
|
|
2513 label('.sysLsrw5b')
|
|
.sysLsrw5b: 0683 c219 st [$19] 2514 st([vAC+1]) #44
|
|
0684 00e7 ld $e7 2515 ld(-50/2) #45
|
|
0685 1403 ld $03,y 2516 ld(hi('REENTER'),Y) #46
|
|
0686 e0cb jmp y,$cb 2517 jmp(Y,'REENTER') #47
|
|
2518 #nop() #48
|
|
2519
|
|
2520 label('SYS_LSRW6_48')
|
|
SYS_LSRW6_48: 0687 1405 ld $05,y 2521 ld(hi('shiftTable'),Y) #15,44 Logical shift right 6 bit (X >> 6)
|
|
0688 008f ld $8f 2522 ld('.sysLsrw6a') #16 Shift low byte
|
|
0689 c21d st [$1d] 2523 st([vTmp]) #17
|
|
068a 0118 ld [$18] 2524 ld([vAC]) #18
|
|
068b 20c0 anda $c0 2525 anda(0b11000000) #19
|
|
068c 401f ora $1f 2526 ora( 0b00011111) #20
|
|
068d e200 jmp y,ac 2527 jmp(Y,AC) #21
|
|
068e fcff bra $ff 2528 bra(255) #22 bra shiftTable+255
|
|
2529 label('.sysLsrw6a')
|
|
.sysLsrw6a: 068f c218 st [$18] 2530 st([vAC]) #26
|
|
0690 0119 ld [$19] 2531 ld([vAC+1]) #27 Transfer bit 8:13
|
|
0691 8200 adda ac 2532 adda(AC) #28
|
|
0692 8200 adda ac 2533 adda(AC) #29
|
|
0693 4118 ora [$18] 2534 ora([vAC]) #30
|
|
0694 c218 st [$18] 2535 st([vAC]) #31
|
|
0695 009c ld $9c 2536 ld('.sysLsrw6b') #32 Shift high byte
|
|
0696 c21d st [$1d] 2537 st([vTmp]) #33
|
|
0697 0119 ld [$19] 2538 ld([vAC+1]) #34
|
|
0698 20c0 anda $c0 2539 anda(0b11000000) #35
|
|
0699 401f ora $1f 2540 ora( 0b00011111) #36
|
|
069a e200 jmp y,ac 2541 jmp(Y,AC) #37
|
|
069b fcff bra $ff 2542 bra(255) #38 bra shiftTable+255
|
|
2543 label('.sysLsrw6b')
|
|
.sysLsrw6b: 069c c219 st [$19] 2544 st([vAC+1]) #42
|
|
069d 1403 ld $03,y 2545 ld(hi('REENTER'),Y) #43
|
|
069e e0cb jmp y,$cb 2546 jmp(Y,'REENTER') #44
|
|
069f 00e8 ld $e8 2547 ld(-48/2) #45
|
|
2548
|
|
2549 label('SYS_LSLW4_46')
|
|
SYS_LSLW4_46: 06a0 1405 ld $05,y 2550 ld(hi('shiftTable'),Y) #15 Logical shift left 4 bit (X << 4)
|
|
06a1 00ae ld $ae 2551 ld('.sysLsrl4') #16
|
|
06a2 c21d st [$1d] 2552 st([vTmp]) #17
|
|
06a3 0119 ld [$19] 2553 ld([vAC+1]) #18
|
|
06a4 8200 adda ac 2554 adda(AC) #19
|
|
06a5 8200 adda ac 2555 adda(AC) #20
|
|
06a6 8200 adda ac 2556 adda(AC) #21
|
|
06a7 8200 adda ac 2557 adda(AC) #22
|
|
06a8 c219 st [$19] 2558 st([vAC+1]) #23
|
|
06a9 0118 ld [$18] 2559 ld([vAC]) #24
|
|
06aa 20f0 anda $f0 2560 anda(0b11110000) #25
|
|
06ab 4007 ora $07 2561 ora( 0b00000111) #26
|
|
06ac e200 jmp y,ac 2562 jmp(Y,AC) #27
|
|
06ad fcff bra $ff 2563 bra(255) #28 bra shiftTable+255
|
|
2564 label('.sysLsrl4')
|
|
.sysLsrl4: 06ae 4119 ora [$19] 2565 ora([vAC+1]) #32
|
|
06af c219 st [$19] 2566 st([vAC+1]) #33
|
|
06b0 0118 ld [$18] 2567 ld([vAC]) #34
|
|
06b1 8200 adda ac 2568 adda(AC) #35
|
|
06b2 8200 adda ac 2569 adda(AC) #36
|
|
06b3 8200 adda ac 2570 adda(AC) #37
|
|
06b4 8200 adda ac 2571 adda(AC) #38
|
|
06b5 c218 st [$18] 2572 st([vAC]) #39
|
|
06b6 00e9 ld $e9 2573 ld(-46/2) #40
|
|
06b7 1403 ld $03,y 2574 ld(hi('REENTER'),Y) #41
|
|
06b8 e0cb jmp y,$cb 2575 jmp(Y,'REENTER') #42
|
|
2576 #nop() #43
|
|
2577
|
|
2578 #-----------------------------------------------------------------------
|
|
2579 # Extension SYS_Read3_40
|
|
2580 #-----------------------------------------------------------------------
|
|
2581
|
|
2582 # Read 3 consecutive bytes from ROM
|
|
2583 #
|
|
2584 # Note: This function a bit obsolete, as it has very limited use. It's
|
|
2585 # effectively an application-specific SYS function for the Pictures
|
|
2586 # application from ROM v1. It requires the ROM data be organized
|
|
2587 # with trampoline3a and trampoline3b fragments, and their address
|
|
2588 # in ROM to be known. Better avoid using this.
|
|
2589 #
|
|
2590 # Variables:
|
|
2591 # sysArgs[0:2] Bytes (out)
|
|
2592 # sysArgs[6:7] ROM pointer (in)
|
|
2593
|
|
2594 label('SYS_Read3_40')
|
|
SYS_Read3_40: 06b9 152b ld [$2b],y 2595 ld([sysArgs+7],Y) #15,32
|
|
06ba e079 jmp y,$79 2596 jmp(Y,128-7) #16 trampoline3a
|
|
06bb 012a ld [$2a] 2597 ld([sysArgs+6]) #17
|
|
2598 label('txReturn')
|
|
txReturn: 06bc c226 st [$26] 2599 st([sysArgs+2]) #34
|
|
06bd 1403 ld $03,y 2600 ld(hi('REENTER'),Y) #35
|
|
06be e0cb jmp y,$cb 2601 jmp(Y,'REENTER') #36
|
|
06bf 00ec ld $ec 2602 ld(-40/2) #37
|
|
2603
|
|
2604 def trampoline3a():
|
|
2605 """Read 3 bytes from ROM page"""
|
|
2606 while pc()&255 < 128-7:
|
|
2607 nop()
|
|
2608 bra(AC) #18
|
|
2609 C('Trampoline for page $%02x00 reading (entry)' % (pc()>>8))
|
|
2610 bra(123) #19
|
|
2611 st([sysArgs+0]) #21
|
|
2612 ld([sysArgs+6]) #22
|
|
2613 adda(1) #23
|
|
2614 bra(AC) #24
|
|
2615 bra(250) #25 trampoline3b
|
|
2616 align(1, size=0x80)
|
|
2617
|
|
2618 def trampoline3b():
|
|
2619 """Read 3 bytes from ROM page (continue)"""
|
|
2620 while pc()&255 < 256-6:
|
|
2621 nop()
|
|
2622 st([sysArgs+1]) #27
|
|
2623 C('Trampoline for page $%02x00 reading (continue)' % (pc()>>8))
|
|
2624 ld([sysArgs+6]) #28
|
|
2625 adda(2) #29
|
|
2626 ld(hi('txReturn'),Y) #30
|
|
2627 bra(AC) #31
|
|
2628 jmp(Y,'txReturn') #32
|
|
2629 align(1, size=0x100)
|
|
2630
|
|
2631 #-----------------------------------------------------------------------
|
|
2632 # Extension SYS_Unpack_56
|
|
2633 #-----------------------------------------------------------------------
|
|
2634
|
|
2635 # Unpack 3 bytes into 4 pixels
|
|
2636 #
|
|
2637 # Variables:
|
|
2638 # sysArgs[0:2] Packed bytes (in)
|
|
2639 # sysArgs[0:3] Pixels (out)
|
|
2640
|
|
2641 label('SYS_Unpack_56')
|
|
SYS_Unpack_56:
|
|
06c0 1407 ld $07,y 2642 ld(soundTable>>8,Y) #15
|
|
06c1 0126 ld [$26] 2643 ld([sysArgs+2]) #16 a[2]>>2
|
|
06c2 5003 ora $03,x 2644 ora(0x03,X) #17
|
|
06c3 0d00 ld [y,x] 2645 ld([Y,X]) #18
|
|
06c4 c227 st [$27] 2646 st([sysArgs+3]) #19 -> Pixel 3
|
|
2647
|
|
06c5 0126 ld [$26] 2648 ld([sysArgs+2]) #20 (a[2]&3)<<4
|
|
06c6 2003 anda $03 2649 anda(0x03) #21
|
|
06c7 8200 adda ac 2650 adda(AC) #22
|
|
06c8 8200 adda ac 2651 adda(AC) #23
|
|
06c9 8200 adda ac 2652 adda(AC) #24
|
|
06ca 8200 adda ac 2653 adda(AC) #25
|
|
06cb c226 st [$26] 2654 st([sysArgs+2]) #26
|
|
06cc 0125 ld [$25] 2655 ld([sysArgs+1]) #27 | a[1]>>4
|
|
06cd 5003 ora $03,x 2656 ora(0x03,X) #28
|
|
06ce 0d00 ld [y,x] 2657 ld([Y,X]) #29
|
|
06cf 5003 ora $03,x 2658 ora(0x03,X) #30
|
|
06d0 0d00 ld [y,x] 2659 ld([Y,X]) #31
|
|
06d1 4126 ora [$26] 2660 ora([sysArgs+2]) #32
|
|
06d2 c226 st [$26] 2661 st([sysArgs+2]) #33 -> Pixel 2
|
|
2662
|
|
06d3 0125 ld [$25] 2663 ld([sysArgs+1]) #34 (a[1]&15)<<2
|
|
06d4 200f anda $0f 2664 anda(0x0f) #35
|
|
06d5 8200 adda ac 2665 adda(AC) #36
|
|
06d6 8200 adda ac 2666 adda(AC) #37
|
|
06d7 c225 st [$25] 2667 st([sysArgs+1]) #38
|
|
2668
|
|
06d8 0124 ld [$24] 2669 ld([sysArgs+0]) #39 | a[0]>>6
|
|
06d9 5003 ora $03,x 2670 ora(0x03,X) #40
|
|
06da 0d00 ld [y,x] 2671 ld([Y,X]) #41
|
|
06db 5003 ora $03,x 2672 ora(0x03,X) #42
|
|
06dc 0d00 ld [y,x] 2673 ld([Y,X]) #43
|
|
06dd 5003 ora $03,x 2674 ora(0x03,X) #44
|
|
06de 0d00 ld [y,x] 2675 ld([Y,X]) #45
|
|
06df 4125 ora [$25] 2676 ora([sysArgs+1]) #46
|
|
06e0 c225 st [$25] 2677 st([sysArgs+1]) #47 -> Pixel 1
|
|
2678
|
|
06e1 0124 ld [$24] 2679 ld([sysArgs+0]) #48 a[1]&63
|
|
06e2 203f anda $3f 2680 anda(0x3f) #49
|
|
06e3 c224 st [$24] 2681 st([sysArgs+0]) #50 -> Pixel 0
|
|
2682
|
|
06e4 1403 ld $03,y 2683 ld(hi('REENTER'),Y) #51
|
|
06e5 e0cb jmp y,$cb 2684 jmp(Y,'REENTER') #52
|
|
06e6 00e4 ld $e4 2685 ld(-56/2) #53
|
|
2686
|
|
2687 #-----------------------------------------------------------------------
|
|
2688 # v6502 right shift instruction
|
|
2689 #-----------------------------------------------------------------------
|
|
2690
|
|
2691 label('v6502_lsr#30')
|
|
v6502_lsr#30: 06e7 1525 ld [$25],y 2692 ld([v6502_ADH],Y) #30 Result
|
|
06e8 ce00 st [y,x] 2693 st([Y,X]) #31
|
|
06e9 c228 st [$28] 2694 st([v6502_Qz]) #32 Z flag
|
|
06ea c229 st [$29] 2695 st([v6502_Qn]) #33 N flag
|
|
06eb 140e ld $0e,y 2696 ld(hi('v6502_next'),Y) #34
|
|
06ec 00ed ld $ed 2697 ld(-38/2) #35
|
|
06ed e020 jmp y,$20 2698 jmp(Y,'v6502_next') #36
|
|
2699 #nop() #37 Overlap
|
|
2700 #
|
|
2701 label('v6502_ror#38')
|
|
v6502_ror#38: 06ee 1525 ld [$25],y 2702 ld([v6502_ADH],Y) #38,38 Result
|
|
06ef 4119 ora [$19] 2703 ora([v6502_BI]) #39 Transfer bit 8
|
|
06f0 ce00 st [y,x] 2704 st([Y,X]) #40
|
|
06f1 c228 st [$28] 2705 st([v6502_Qz]) #41 Z flag
|
|
06f2 c229 st [$29] 2706 st([v6502_Qn]) #42 N flag
|
|
06f3 140e ld $0e,y 2707 ld(hi('v6502_next'),Y) #43
|
|
06f4 e020 jmp y,$20 2708 jmp(Y,'v6502_next') #44
|
|
06f5 00e9 ld $e9 2709 ld(-46/2) #45
|
|
2710
|
|
2711 label("sys_MultiplyBytes#114")
|
|
sys_MultiplyBytes#114:
|
|
06f6 8119 adda [$19] 2712 adda([vAC + 1]) #114
|
|
06f7 c219 st [$19] 2713 st([vAC + 1]) #115
|
|
06f8 1403 ld $03,y 2714 ld(hi('NEXTY'), Y) #116
|
|
06f9 e000 jmp y,$00 2715 jmp(Y, 'NEXTY') #117
|
|
06fa 00c4 ld $c4 2716 ld(-120/2) #118
|
|
2717 #-----------------------------------------------------------------------
|
|
2718 #
|
|
2719 # $0700 ROM page 7-8: Gigatron font data
|
|
2720 #
|
|
2721 #-----------------------------------------------------------------------
|
|
2722
|
|
06fb 0200 nop 2723 align(0x100, size=0x100)
|
|
06fc 0200 nop
|
|
06fd 0200 nop
|
|
* 5 times
|
|
2724
|
|
2725 label('font32up')
|
|
2726 for ch in range(32, 32+50):
|
|
2727 comment = 'Char %s' % repr(chr(ch))
|
|
2728 for byte in font.font[ch-32]:
|
|
2729 ld(byte)
|
|
font32up: 0700 0000 ld $00 ;Char ' '
|
|
0701 0000 ld $00
|
|
0702 0000 ld $00
|
|
* 5 times
|
|
0705 0000 ld $00 ;Char '!'
|
|
0706 0000 ld $00
|
|
0707 00fa ld $fa
|
|
0708 0000 ld $00
|
|
0709 0000 ld $00
|
|
070a 00a0 ld $a0 ;Char '"'
|
|
070b 00c0 ld $c0
|
|
070c 0000 ld $00
|
|
070d 00a0 ld $a0
|
|
070e 00c0 ld $c0
|
|
070f 0028 ld $28 ;Char '#'
|
|
0710 00fe ld $fe
|
|
0711 0028 ld $28
|
|
0712 00fe ld $fe
|
|
0713 0028 ld $28
|
|
0714 0024 ld $24 ;Char '$'
|
|
0715 0054 ld $54
|
|
0716 00fe ld $fe
|
|
0717 0054 ld $54
|
|
0718 0048 ld $48
|
|
0719 00c4 ld $c4 ;Char '%'
|
|
071a 00c8 ld $c8
|
|
071b 0010 ld $10
|
|
071c 0026 ld $26
|
|
071d 0046 ld $46
|
|
071e 006c ld $6c ;Char '&'
|
|
071f 0092 ld $92
|
|
0720 006a ld $6a
|
|
0721 0004 ld $04
|
|
0722 000a ld $0a
|
|
0723 0000 ld $00 ;Char "'"
|
|
0724 00a0 ld $a0
|
|
0725 00c0 ld $c0
|
|
0726 0000 ld $00
|
|
0727 0000 ld $00
|
|
0728 0000 ld $00 ;Char '('
|
|
0729 0038 ld $38
|
|
072a 0044 ld $44
|
|
072b 0082 ld $82
|
|
072c 0000 ld $00
|
|
072d 0000 ld $00 ;Char ')'
|
|
072e 0082 ld $82
|
|
072f 0044 ld $44
|
|
0730 0038 ld $38
|
|
0731 0000 ld $00
|
|
0732 0028 ld $28 ;Char '*'
|
|
0733 0010 ld $10
|
|
0734 007c ld $7c
|
|
0735 0010 ld $10
|
|
0736 0028 ld $28
|
|
0737 0010 ld $10 ;Char '+'
|
|
0738 0010 ld $10
|
|
0739 007c ld $7c
|
|
073a 0010 ld $10
|
|
073b 0010 ld $10
|
|
073c 0000 ld $00 ;Char ','
|
|
073d 0005 ld $05
|
|
073e 0006 ld $06
|
|
073f 0000 ld $00
|
|
0740 0000 ld $00
|
|
0741 0010 ld $10 ;Char '-'
|
|
0742 0010 ld $10
|
|
0743 0010 ld $10
|
|
* 5 times
|
|
0746 0000 ld $00 ;Char '.'
|
|
0747 0002 ld $02
|
|
0748 0002 ld $02
|
|
0749 0000 ld $00
|
|
074a 0000 ld $00
|
|
074b 0000 ld $00 ;Char '/'
|
|
074c 0006 ld $06
|
|
074d 0018 ld $18
|
|
074e 0060 ld $60
|
|
074f 0000 ld $00
|
|
0750 007c ld $7c ;Char '0'
|
|
0751 008a ld $8a
|
|
0752 0092 ld $92
|
|
0753 00a2 ld $a2
|
|
0754 007c ld $7c
|
|
0755 0022 ld $22 ;Char '1'
|
|
0756 0042 ld $42
|
|
0757 00fe ld $fe
|
|
0758 0002 ld $02
|
|
0759 0002 ld $02
|
|
075a 0046 ld $46 ;Char '2'
|
|
075b 008a ld $8a
|
|
075c 0092 ld $92
|
|
075d 0092 ld $92
|
|
075e 0062 ld $62
|
|
075f 0044 ld $44 ;Char '3'
|
|
0760 0082 ld $82
|
|
0761 0092 ld $92
|
|
0762 0092 ld $92
|
|
0763 006c ld $6c
|
|
0764 0018 ld $18 ;Char '4'
|
|
0765 0028 ld $28
|
|
0766 0048 ld $48
|
|
0767 00fe ld $fe
|
|
0768 0008 ld $08
|
|
0769 00e4 ld $e4 ;Char '5'
|
|
076a 00a2 ld $a2
|
|
076b 00a2 ld $a2
|
|
076c 00a2 ld $a2
|
|
076d 009c ld $9c
|
|
076e 003c ld $3c ;Char '6'
|
|
076f 0052 ld $52
|
|
0770 0092 ld $92
|
|
0771 0092 ld $92
|
|
0772 000c ld $0c
|
|
0773 0080 ld $80 ;Char '7'
|
|
0774 008e ld $8e
|
|
0775 0090 ld $90
|
|
0776 00a0 ld $a0
|
|
0777 00c0 ld $c0
|
|
0778 006c ld $6c ;Char '8'
|
|
0779 0092 ld $92
|
|
077a 0092 ld $92
|
|
077b 0092 ld $92
|
|
077c 006c ld $6c
|
|
077d 0060 ld $60 ;Char '9'
|
|
077e 0092 ld $92
|
|
077f 0092 ld $92
|
|
0780 0094 ld $94
|
|
0781 0078 ld $78
|
|
0782 0000 ld $00 ;Char ':'
|
|
0783 0024 ld $24
|
|
0784 0024 ld $24
|
|
0785 0000 ld $00
|
|
0786 0000 ld $00
|
|
0787 0000 ld $00 ;Char ';'
|
|
0788 0025 ld $25
|
|
0789 0026 ld $26
|
|
078a 0000 ld $00
|
|
078b 0000 ld $00
|
|
078c 0010 ld $10 ;Char '<'
|
|
078d 0028 ld $28
|
|
078e 0044 ld $44
|
|
078f 0082 ld $82
|
|
0790 0000 ld $00
|
|
0791 0028 ld $28 ;Char '='
|
|
0792 0028 ld $28
|
|
0793 0028 ld $28
|
|
* 5 times
|
|
0796 0000 ld $00 ;Char '>'
|
|
0797 0082 ld $82
|
|
0798 0044 ld $44
|
|
0799 0028 ld $28
|
|
079a 0010 ld $10
|
|
079b 0040 ld $40 ;Char '?'
|
|
079c 0080 ld $80
|
|
079d 008a ld $8a
|
|
079e 0090 ld $90
|
|
079f 0060 ld $60
|
|
07a0 007c ld $7c ;Char '@'
|
|
07a1 0082 ld $82
|
|
07a2 00ba ld $ba
|
|
07a3 00aa ld $aa
|
|
07a4 0078 ld $78
|
|
07a5 003e ld $3e ;Char 'A'
|
|
07a6 0048 ld $48
|
|
07a7 0088 ld $88
|
|
07a8 0048 ld $48
|
|
07a9 003e ld $3e
|
|
07aa 00fe ld $fe ;Char 'B'
|
|
07ab 0092 ld $92
|
|
07ac 0092 ld $92
|
|
07ad 0092 ld $92
|
|
07ae 006c ld $6c
|
|
07af 007c ld $7c ;Char 'C'
|
|
07b0 0082 ld $82
|
|
07b1 0082 ld $82
|
|
07b2 0082 ld $82
|
|
07b3 0044 ld $44
|
|
07b4 00fe ld $fe ;Char 'D'
|
|
07b5 0082 ld $82
|
|
07b6 0082 ld $82
|
|
07b7 0044 ld $44
|
|
07b8 0038 ld $38
|
|
07b9 00fe ld $fe ;Char 'E'
|
|
07ba 0092 ld $92
|
|
07bb 0092 ld $92
|
|
07bc 0092 ld $92
|
|
07bd 0082 ld $82
|
|
07be 00fe ld $fe ;Char 'F'
|
|
07bf 0090 ld $90
|
|
07c0 0090 ld $90
|
|
07c1 0090 ld $90
|
|
07c2 0080 ld $80
|
|
07c3 007c ld $7c ;Char 'G'
|
|
07c4 0082 ld $82
|
|
07c5 0082 ld $82
|
|
07c6 0092 ld $92
|
|
07c7 005c ld $5c
|
|
07c8 00fe ld $fe ;Char 'H'
|
|
07c9 0010 ld $10
|
|
07ca 0010 ld $10
|
|
07cb 0010 ld $10
|
|
07cc 00fe ld $fe
|
|
07cd 0000 ld $00 ;Char 'I'
|
|
07ce 0082 ld $82
|
|
07cf 00fe ld $fe
|
|
07d0 0082 ld $82
|
|
07d1 0000 ld $00
|
|
07d2 0004 ld $04 ;Char 'J'
|
|
07d3 0002 ld $02
|
|
07d4 0082 ld $82
|
|
07d5 00fc ld $fc
|
|
07d6 0080 ld $80
|
|
07d7 00fe ld $fe ;Char 'K'
|
|
07d8 0010 ld $10
|
|
07d9 0028 ld $28
|
|
07da 0044 ld $44
|
|
07db 0082 ld $82
|
|
07dc 00fe ld $fe ;Char 'L'
|
|
07dd 0002 ld $02
|
|
07de 0002 ld $02
|
|
07df 0002 ld $02
|
|
07e0 0002 ld $02
|
|
07e1 00fe ld $fe ;Char 'M'
|
|
07e2 0040 ld $40
|
|
07e3 0030 ld $30
|
|
07e4 0040 ld $40
|
|
07e5 00fe ld $fe
|
|
07e6 00fe ld $fe ;Char 'N'
|
|
07e7 0020 ld $20
|
|
07e8 0010 ld $10
|
|
07e9 0008 ld $08
|
|
07ea 00fe ld $fe
|
|
07eb 007c ld $7c ;Char 'O'
|
|
07ec 0082 ld $82
|
|
07ed 0082 ld $82
|
|
07ee 0082 ld $82
|
|
07ef 007c ld $7c
|
|
07f0 00fe ld $fe ;Char 'P'
|
|
07f1 0090 ld $90
|
|
07f2 0090 ld $90
|
|
07f3 0090 ld $90
|
|
07f4 0060 ld $60
|
|
07f5 007c ld $7c ;Char 'Q'
|
|
07f6 0082 ld $82
|
|
07f7 008a ld $8a
|
|
07f8 0084 ld $84
|
|
07f9 007a ld $7a
|
|
2730 comment = C(comment)
|
|
2731
|
|
07fa 0200 nop 2732 trampoline()
|
|
07fb fe00 bra ac ;+-----------------------------------+
|
|
07fc fcfd bra $07fd ;| |
|
|
07fd 1404 ld $04,y ;| Trampoline for page $0700 lookups |
|
|
07fe e068 jmp y,$68 ;| |
|
|
07ff c218 st [$18] ;+-----------------------------------+
|
|
2733
|
|
2734 #-----------------------------------------------------------------------
|
|
2735
|
|
2736 align(0x100, size=0x100)
|
|
2737
|
|
2738 label('font82up')
|
|
2739 for ch in range(32+50, 132):
|
|
2740 comment = 'Char %s' % repr(chr(ch))
|
|
2741 for byte in font.font[ch-32]:
|
|
2742 ld(byte)
|
|
font82up: 0800 00fe ld $fe ;Char 'R'
|
|
0801 0090 ld $90
|
|
0802 0098 ld $98
|
|
0803 0094 ld $94
|
|
0804 0062 ld $62
|
|
0805 0062 ld $62 ;Char 'S'
|
|
0806 0092 ld $92
|
|
0807 0092 ld $92
|
|
0808 0092 ld $92
|
|
0809 000c ld $0c
|
|
080a 0080 ld $80 ;Char 'T'
|
|
080b 0080 ld $80
|
|
080c 00fe ld $fe
|
|
080d 0080 ld $80
|
|
080e 0080 ld $80
|
|
080f 00fc ld $fc ;Char 'U'
|
|
0810 0002 ld $02
|
|
0811 0002 ld $02
|
|
0812 0002 ld $02
|
|
0813 00fc ld $fc
|
|
0814 00f0 ld $f0 ;Char 'V'
|
|
0815 000c ld $0c
|
|
0816 0002 ld $02
|
|
0817 000c ld $0c
|
|
0818 00f0 ld $f0
|
|
0819 00fe ld $fe ;Char 'W'
|
|
081a 0004 ld $04
|
|
081b 0018 ld $18
|
|
081c 0004 ld $04
|
|
081d 00fe ld $fe
|
|
081e 00c6 ld $c6 ;Char 'X'
|
|
081f 0028 ld $28
|
|
0820 0010 ld $10
|
|
0821 0028 ld $28
|
|
0822 00c6 ld $c6
|
|
0823 00e0 ld $e0 ;Char 'Y'
|
|
0824 0010 ld $10
|
|
0825 000e ld $0e
|
|
0826 0010 ld $10
|
|
0827 00e0 ld $e0
|
|
0828 0086 ld $86 ;Char 'Z'
|
|
0829 008a ld $8a
|
|
082a 0092 ld $92
|
|
082b 00a2 ld $a2
|
|
082c 00c2 ld $c2
|
|
082d 0000 ld $00 ;Char '['
|
|
082e 00fe ld $fe
|
|
082f 0082 ld $82
|
|
0830 0082 ld $82
|
|
0831 0000 ld $00
|
|
0832 0000 ld $00 ;Char '\\'
|
|
0833 0060 ld $60
|
|
0834 0018 ld $18
|
|
0835 0006 ld $06
|
|
0836 0000 ld $00
|
|
0837 0000 ld $00 ;Char ']'
|
|
0838 0082 ld $82
|
|
0839 0082 ld $82
|
|
083a 00fe ld $fe
|
|
083b 0000 ld $00
|
|
083c 0020 ld $20 ;Char '^'
|
|
083d 0040 ld $40
|
|
083e 0080 ld $80
|
|
083f 0040 ld $40
|
|
0840 0020 ld $20
|
|
0841 0002 ld $02 ;Char '_'
|
|
0842 0002 ld $02
|
|
0843 0002 ld $02
|
|
* 5 times
|
|
0846 0000 ld $00 ;Char '`'
|
|
0847 0000 ld $00
|
|
0848 00c0 ld $c0
|
|
0849 00a0 ld $a0
|
|
084a 0000 ld $00
|
|
084b 0004 ld $04 ;Char 'a'
|
|
084c 002a ld $2a
|
|
084d 002a ld $2a
|
|
084e 002a ld $2a
|
|
084f 001e ld $1e
|
|
0850 00fe ld $fe ;Char 'b'
|
|
0851 0022 ld $22
|
|
0852 0022 ld $22
|
|
0853 0022 ld $22
|
|
0854 001c ld $1c
|
|
0855 001c ld $1c ;Char 'c'
|
|
0856 0022 ld $22
|
|
0857 0022 ld $22
|
|
0858 0022 ld $22
|
|
0859 0002 ld $02
|
|
085a 001c ld $1c ;Char 'd'
|
|
085b 0022 ld $22
|
|
085c 0022 ld $22
|
|
085d 0022 ld $22
|
|
085e 00fe ld $fe
|
|
085f 001c ld $1c ;Char 'e'
|
|
0860 002a ld $2a
|
|
0861 002a ld $2a
|
|
0862 002a ld $2a
|
|
0863 0018 ld $18
|
|
0864 0010 ld $10 ;Char 'f'
|
|
0865 007e ld $7e
|
|
0866 0090 ld $90
|
|
0867 0080 ld $80
|
|
0868 0040 ld $40
|
|
0869 0018 ld $18 ;Char 'g'
|
|
086a 0025 ld $25
|
|
086b 0025 ld $25
|
|
086c 0025 ld $25
|
|
086d 001e ld $1e
|
|
086e 00fe ld $fe ;Char 'h'
|
|
086f 0020 ld $20
|
|
0870 0020 ld $20
|
|
0871 0020 ld $20
|
|
0872 001e ld $1e
|
|
0873 0000 ld $00 ;Char 'i'
|
|
0874 0022 ld $22
|
|
0875 00be ld $be
|
|
0876 0002 ld $02
|
|
0877 0000 ld $00
|
|
0878 0002 ld $02 ;Char 'j'
|
|
0879 0001 ld $01
|
|
087a 0021 ld $21
|
|
087b 00be ld $be
|
|
087c 0000 ld $00
|
|
087d 00fe ld $fe ;Char 'k'
|
|
087e 0008 ld $08
|
|
087f 0018 ld $18
|
|
0880 0024 ld $24
|
|
0881 0002 ld $02
|
|
0882 0000 ld $00 ;Char 'l'
|
|
0883 0082 ld $82
|
|
0884 00fe ld $fe
|
|
0885 0002 ld $02
|
|
0886 0000 ld $00
|
|
0887 003e ld $3e ;Char 'm'
|
|
0888 0020 ld $20
|
|
0889 001c ld $1c
|
|
088a 0020 ld $20
|
|
088b 001e ld $1e
|
|
088c 003e ld $3e ;Char 'n'
|
|
088d 0010 ld $10
|
|
088e 0020 ld $20
|
|
088f 0020 ld $20
|
|
0890 001e ld $1e
|
|
0891 001c ld $1c ;Char 'o'
|
|
0892 0022 ld $22
|
|
0893 0022 ld $22
|
|
0894 0022 ld $22
|
|
0895 001c ld $1c
|
|
0896 003f ld $3f ;Char 'p'
|
|
0897 0024 ld $24
|
|
0898 0024 ld $24
|
|
0899 0024 ld $24
|
|
089a 0018 ld $18
|
|
089b 0018 ld $18 ;Char 'q'
|
|
089c 0024 ld $24
|
|
089d 0024 ld $24
|
|
089e 0024 ld $24
|
|
089f 003f ld $3f
|
|
08a0 003e ld $3e ;Char 'r'
|
|
08a1 0010 ld $10
|
|
08a2 0020 ld $20
|
|
08a3 0020 ld $20
|
|
08a4 0010 ld $10
|
|
08a5 0012 ld $12 ;Char 's'
|
|
08a6 002a ld $2a
|
|
08a7 002a ld $2a
|
|
08a8 002a ld $2a
|
|
08a9 0004 ld $04
|
|
08aa 0020 ld $20 ;Char 't'
|
|
08ab 00fc ld $fc
|
|
08ac 0022 ld $22
|
|
08ad 0002 ld $02
|
|
08ae 0004 ld $04
|
|
08af 003c ld $3c ;Char 'u'
|
|
08b0 0002 ld $02
|
|
08b1 0002 ld $02
|
|
08b2 0004 ld $04
|
|
08b3 003e ld $3e
|
|
08b4 0038 ld $38 ;Char 'v'
|
|
08b5 0004 ld $04
|
|
08b6 0002 ld $02
|
|
08b7 0004 ld $04
|
|
08b8 0038 ld $38
|
|
08b9 003c ld $3c ;Char 'w'
|
|
08ba 0002 ld $02
|
|
08bb 000c ld $0c
|
|
08bc 0002 ld $02
|
|
08bd 003c ld $3c
|
|
08be 0022 ld $22 ;Char 'x'
|
|
08bf 0014 ld $14
|
|
08c0 0008 ld $08
|
|
08c1 0014 ld $14
|
|
08c2 0022 ld $22
|
|
08c3 0038 ld $38 ;Char 'y'
|
|
08c4 0005 ld $05
|
|
08c5 0005 ld $05
|
|
08c6 0005 ld $05
|
|
08c7 003e ld $3e
|
|
08c8 0022 ld $22 ;Char 'z'
|
|
08c9 0026 ld $26
|
|
08ca 002a ld $2a
|
|
08cb 0032 ld $32
|
|
08cc 0022 ld $22
|
|
08cd 0010 ld $10 ;Char '{'
|
|
08ce 006c ld $6c
|
|
08cf 0082 ld $82
|
|
08d0 0082 ld $82
|
|
08d1 0000 ld $00
|
|
08d2 0000 ld $00 ;Char '|'
|
|
08d3 0000 ld $00
|
|
08d4 00fe ld $fe
|
|
08d5 0000 ld $00
|
|
08d6 0000 ld $00
|
|
08d7 0000 ld $00 ;Char '}'
|
|
08d8 0082 ld $82
|
|
08d9 0082 ld $82
|
|
08da 006c ld $6c
|
|
08db 0010 ld $10
|
|
08dc 0040 ld $40 ;Char '~'
|
|
08dd 0080 ld $80
|
|
08de 0040 ld $40
|
|
08df 0020 ld $20
|
|
08e0 0040 ld $40
|
|
08e1 00fe ld $fe ;Char '\x7f'
|
|
08e2 00fe ld $fe
|
|
08e3 00fe ld $fe
|
|
* 5 times
|
|
08e6 0010 ld $10 ;Char '\x80'
|
|
08e7 0038 ld $38
|
|
08e8 0054 ld $54
|
|
08e9 0010 ld $10
|
|
08ea 0010 ld $10
|
|
08eb 0010 ld $10 ;Char '\x81'
|
|
08ec 0020 ld $20
|
|
08ed 007c ld $7c
|
|
08ee 0020 ld $20
|
|
08ef 0010 ld $10
|
|
08f0 0010 ld $10 ;Char '\x82'
|
|
08f1 0010 ld $10
|
|
08f2 0054 ld $54
|
|
08f3 0038 ld $38
|
|
08f4 0010 ld $10
|
|
08f5 0010 ld $10 ;Char '\x83'
|
|
08f6 0008 ld $08
|
|
08f7 007c ld $7c
|
|
08f8 0008 ld $08
|
|
08f9 0010 ld $10
|
|
2743 comment = C(comment)
|
|
2744
|
|
08fa 0200 nop 2745 trampoline()
|
|
08fb fe00 bra ac ;+-----------------------------------+
|
|
08fc fcfd bra $08fd ;| |
|
|
08fd 1404 ld $04,y ;| Trampoline for page $0800 lookups |
|
|
08fe e068 jmp y,$68 ;| |
|
|
08ff c218 st [$18] ;+-----------------------------------+
|
|
2746
|
|
2747 #-----------------------------------------------------------------------
|
|
2748 #
|
|
2749 # $0900 ROM page 9: Key table for music
|
|
2750 #
|
|
2751 #-----------------------------------------------------------------------
|
|
2752
|
|
2753 align(0x100, size=0x100)
|
|
2754 notes = 'CCDDEFFGGAAB'
|
|
2755 sampleRate = cpuClock / 200.0 / 4
|
|
2756 label('notesTable')
|
|
notesTable: 0900 0000 ld $00 2757 ld(0)
|
|
0901 0000 ld $00 2758 ld(0)
|
|
2759 for i in range(0, 250, 2):
|
|
2760 j = i//2-1
|
|
2761 freq = 440.0*2.0**((j-57)/12.0)
|
|
2762 if j>=0 and freq <= sampleRate/2.0:
|
|
2763 key = int(round(32768 * freq / sampleRate))
|
|
2764 octave, note = j//12, notes[j%12]
|
|
2765 sharp = '-' if notes[j%12-1] != note else '#'
|
|
2766 comment = '%s%s%s (%0.1f Hz)' % (note, sharp, octave, freq)
|
|
2767 ld(key&127); C(comment); ld(key>>7)
|
|
0902 0045 ld $45 ;C-0 (16.4 Hz)
|
|
0903 0000 ld $00
|
|
0904 0049 ld $49 ;C#0 (17.3 Hz)
|
|
0905 0000 ld $00
|
|
0906 004d ld $4d ;D-0 (18.4 Hz)
|
|
0907 0000 ld $00
|
|
0908 0052 ld $52 ;D#0 (19.4 Hz)
|
|
0909 0000 ld $00
|
|
090a 0056 ld $56 ;E-0 (20.6 Hz)
|
|
090b 0000 ld $00
|
|
090c 005c ld $5c ;F-0 (21.8 Hz)
|
|
090d 0000 ld $00
|
|
090e 0061 ld $61 ;F#0 (23.1 Hz)
|
|
090f 0000 ld $00
|
|
0910 0067 ld $67 ;G-0 (24.5 Hz)
|
|
0911 0000 ld $00
|
|
0912 006d ld $6d ;G#0 (26.0 Hz)
|
|
0913 0000 ld $00
|
|
0914 0073 ld $73 ;A-0 (27.5 Hz)
|
|
0915 0000 ld $00
|
|
0916 007a ld $7a ;A#0 (29.1 Hz)
|
|
0917 0000 ld $00
|
|
0918 0001 ld $01 ;B-0 (30.9 Hz)
|
|
0919 0001 ld $01
|
|
091a 0009 ld $09 ;C-1 (32.7 Hz)
|
|
091b 0001 ld $01
|
|
091c 0011 ld $11 ;C#1 (34.6 Hz)
|
|
091d 0001 ld $01
|
|
091e 001a ld $1a ;D-1 (36.7 Hz)
|
|
091f 0001 ld $01
|
|
0920 0023 ld $23 ;D#1 (38.9 Hz)
|
|
0921 0001 ld $01
|
|
0922 002d ld $2d ;E-1 (41.2 Hz)
|
|
0923 0001 ld $01
|
|
0924 0037 ld $37 ;F-1 (43.7 Hz)
|
|
0925 0001 ld $01
|
|
0926 0042 ld $42 ;F#1 (46.2 Hz)
|
|
0927 0001 ld $01
|
|
0928 004e ld $4e ;G-1 (49.0 Hz)
|
|
0929 0001 ld $01
|
|
092a 005a ld $5a ;G#1 (51.9 Hz)
|
|
092b 0001 ld $01
|
|
092c 0067 ld $67 ;A-1 (55.0 Hz)
|
|
092d 0001 ld $01
|
|
092e 0074 ld $74 ;A#1 (58.3 Hz)
|
|
092f 0001 ld $01
|
|
0930 0003 ld $03 ;B-1 (61.7 Hz)
|
|
0931 0002 ld $02
|
|
0932 0012 ld $12 ;C-2 (65.4 Hz)
|
|
0933 0002 ld $02
|
|
0934 0023 ld $23 ;C#2 (69.3 Hz)
|
|
0935 0002 ld $02
|
|
0936 0034 ld $34 ;D-2 (73.4 Hz)
|
|
0937 0002 ld $02
|
|
0938 0046 ld $46 ;D#2 (77.8 Hz)
|
|
0939 0002 ld $02
|
|
093a 005a ld $5a ;E-2 (82.4 Hz)
|
|
093b 0002 ld $02
|
|
093c 006e ld $6e ;F-2 (87.3 Hz)
|
|
093d 0002 ld $02
|
|
093e 0004 ld $04 ;F#2 (92.5 Hz)
|
|
093f 0003 ld $03
|
|
0940 001b ld $1b ;G-2 (98.0 Hz)
|
|
0941 0003 ld $03
|
|
0942 0033 ld $33 ;G#2 (103.8 Hz)
|
|
0943 0003 ld $03
|
|
0944 004d ld $4d ;A-2 (110.0 Hz)
|
|
0945 0003 ld $03
|
|
0946 0069 ld $69 ;A#2 (116.5 Hz)
|
|
0947 0003 ld $03
|
|
0948 0006 ld $06 ;B-2 (123.5 Hz)
|
|
0949 0004 ld $04
|
|
094a 0025 ld $25 ;C-3 (130.8 Hz)
|
|
094b 0004 ld $04
|
|
094c 0045 ld $45 ;C#3 (138.6 Hz)
|
|
094d 0004 ld $04
|
|
094e 0068 ld $68 ;D-3 (146.8 Hz)
|
|
094f 0004 ld $04
|
|
0950 000c ld $0c ;D#3 (155.6 Hz)
|
|
0951 0005 ld $05
|
|
0952 0033 ld $33 ;E-3 (164.8 Hz)
|
|
0953 0005 ld $05
|
|
0954 005c ld $5c ;F-3 (174.6 Hz)
|
|
0955 0005 ld $05
|
|
0956 0008 ld $08 ;F#3 (185.0 Hz)
|
|
0957 0006 ld $06
|
|
0958 0036 ld $36 ;G-3 (196.0 Hz)
|
|
0959 0006 ld $06
|
|
095a 0067 ld $67 ;G#3 (207.7 Hz)
|
|
095b 0006 ld $06
|
|
095c 001b ld $1b ;A-3 (220.0 Hz)
|
|
095d 0007 ld $07
|
|
095e 0052 ld $52 ;A#3 (233.1 Hz)
|
|
095f 0007 ld $07
|
|
0960 000c ld $0c ;B-3 (246.9 Hz)
|
|
0961 0008 ld $08
|
|
0962 0049 ld $49 ;C-4 (261.6 Hz)
|
|
0963 0008 ld $08
|
|
0964 000b ld $0b ;C#4 (277.2 Hz)
|
|
0965 0009 ld $09
|
|
0966 0050 ld $50 ;D-4 (293.7 Hz)
|
|
0967 0009 ld $09
|
|
0968 0019 ld $19 ;D#4 (311.1 Hz)
|
|
0969 000a ld $0a
|
|
096a 0067 ld $67 ;E-4 (329.6 Hz)
|
|
096b 000a ld $0a
|
|
096c 0039 ld $39 ;F-4 (349.2 Hz)
|
|
096d 000b ld $0b
|
|
096e 0010 ld $10 ;F#4 (370.0 Hz)
|
|
096f 000c ld $0c
|
|
0970 006c ld $6c ;G-4 (392.0 Hz)
|
|
0971 000c ld $0c
|
|
0972 004e ld $4e ;G#4 (415.3 Hz)
|
|
0973 000d ld $0d
|
|
0974 0035 ld $35 ;A-4 (440.0 Hz)
|
|
0975 000e ld $0e
|
|
0976 0023 ld $23 ;A#4 (466.2 Hz)
|
|
0977 000f ld $0f
|
|
0978 0017 ld $17 ;B-4 (493.9 Hz)
|
|
0979 0010 ld $10
|
|
097a 0013 ld $13 ;C-5 (523.3 Hz)
|
|
097b 0011 ld $11
|
|
097c 0015 ld $15 ;C#5 (554.4 Hz)
|
|
097d 0012 ld $12
|
|
097e 001f ld $1f ;D-5 (587.3 Hz)
|
|
097f 0013 ld $13
|
|
0980 0032 ld $32 ;D#5 (622.3 Hz)
|
|
0981 0014 ld $14
|
|
0982 004d ld $4d ;E-5 (659.3 Hz)
|
|
0983 0015 ld $15
|
|
0984 0072 ld $72 ;F-5 (698.5 Hz)
|
|
0985 0016 ld $16
|
|
0986 0020 ld $20 ;F#5 (740.0 Hz)
|
|
0987 0018 ld $18
|
|
0988 0058 ld $58 ;G-5 (784.0 Hz)
|
|
0989 0019 ld $19
|
|
098a 001c ld $1c ;G#5 (830.6 Hz)
|
|
098b 001b ld $1b
|
|
098c 006b ld $6b ;A-5 (880.0 Hz)
|
|
098d 001c ld $1c
|
|
098e 0046 ld $46 ;A#5 (932.3 Hz)
|
|
098f 001e ld $1e
|
|
0990 002f ld $2f ;B-5 (987.8 Hz)
|
|
0991 0020 ld $20
|
|
0992 0025 ld $25 ;C-6 (1046.5 Hz)
|
|
0993 0022 ld $22
|
|
0994 002a ld $2a ;C#6 (1108.7 Hz)
|
|
0995 0024 ld $24
|
|
0996 003f ld $3f ;D-6 (1174.7 Hz)
|
|
0997 0026 ld $26
|
|
0998 0064 ld $64 ;D#6 (1244.5 Hz)
|
|
0999 0028 ld $28
|
|
099a 001a ld $1a ;E-6 (1318.5 Hz)
|
|
099b 002b ld $2b
|
|
099c 0063 ld $63 ;F-6 (1396.9 Hz)
|
|
099d 002d ld $2d
|
|
099e 003f ld $3f ;F#6 (1480.0 Hz)
|
|
099f 0030 ld $30
|
|
09a0 0031 ld $31 ;G-6 (1568.0 Hz)
|
|
09a1 0033 ld $33
|
|
09a2 0038 ld $38 ;G#6 (1661.2 Hz)
|
|
09a3 0036 ld $36
|
|
09a4 0056 ld $56 ;A-6 (1760.0 Hz)
|
|
09a5 0039 ld $39
|
|
09a6 000d ld $0d ;A#6 (1864.7 Hz)
|
|
09a7 003d ld $3d
|
|
09a8 005e ld $5e ;B-6 (1975.5 Hz)
|
|
09a9 0040 ld $40
|
|
09aa 004b ld $4b ;C-7 (2093.0 Hz)
|
|
09ab 0044 ld $44
|
|
09ac 0055 ld $55 ;C#7 (2217.5 Hz)
|
|
09ad 0048 ld $48
|
|
09ae 007e ld $7e ;D-7 (2349.3 Hz)
|
|
09af 004c ld $4c
|
|
09b0 0048 ld $48 ;D#7 (2489.0 Hz)
|
|
09b1 0051 ld $51
|
|
09b2 0034 ld $34 ;E-7 (2637.0 Hz)
|
|
09b3 0056 ld $56
|
|
09b4 0046 ld $46 ;F-7 (2793.8 Hz)
|
|
09b5 005b ld $5b
|
|
09b6 007f ld $7f ;F#7 (2960.0 Hz)
|
|
09b7 0060 ld $60
|
|
09b8 0061 ld $61 ;G-7 (3136.0 Hz)
|
|
09b9 0066 ld $66
|
|
09ba 006f ld $6f ;G#7 (3322.4 Hz)
|
|
09bb 006c ld $6c
|
|
09bc 002c ld $2c ;A-7 (3520.0 Hz)
|
|
09bd 0073 ld $73
|
|
09be 001a ld $1a ;A#7 (3729.3 Hz)
|
|
09bf 007a ld $7a
|
|
2768
|
|
09c0 0200 nop 2769 trampoline()
|
|
09c1 0200 nop
|
|
09c2 0200 nop
|
|
* 59 times
|
|
09fb fe00 bra ac ;+-----------------------------------+
|
|
09fc fcfd bra $09fd ;| |
|
|
09fd 1404 ld $04,y ;| Trampoline for page $0900 lookups |
|
|
09fe e068 jmp y,$68 ;| |
|
|
09ff c218 st [$18] ;+-----------------------------------+
|
|
2770
|
|
2771 #-----------------------------------------------------------------------
|
|
2772 #
|
|
2773 # $0a00 ROM page 10: Inversion table
|
|
2774 #
|
|
2775 #-----------------------------------------------------------------------
|
|
2776
|
|
2777 align(0x100, size=0x100)
|
|
2778 label('invTable')
|
|
2779
|
|
2780 # Unit 64, table offset 16 (=1/4), value offset 1: (x+16)*(y+1) == 64*64 - e
|
|
2781 for i in range(251):
|
|
invTable: 0a00 00ff ld $ff 2782 ld(4096//(i+16)-1)
|
|
0a01 00ef ld $ef
|
|
0a02 00e2 ld $e2
|
|
0a03 00d6 ld $d6
|
|
0a04 00cb ld $cb
|
|
0a05 00c2 ld $c2
|
|
0a06 00b9 ld $b9
|
|
0a07 00b1 ld $b1
|
|
0a08 00a9 ld $a9
|
|
0a09 00a2 ld $a2
|
|
0a0a 009c ld $9c
|
|
0a0b 0096 ld $96
|
|
0a0c 0091 ld $91
|
|
0a0d 008c ld $8c
|
|
0a0e 0087 ld $87
|
|
0a0f 0083 ld $83
|
|
0a10 007f ld $7f
|
|
0a11 007b ld $7b
|
|
0a12 0077 ld $77
|
|
0a13 0074 ld $74
|
|
0a14 0070 ld $70
|
|
0a15 006d ld $6d
|
|
0a16 006a ld $6a
|
|
0a17 0068 ld $68
|
|
0a18 0065 ld $65
|
|
0a19 0062 ld $62
|
|
0a1a 0060 ld $60
|
|
0a1b 005e ld $5e
|
|
0a1c 005c ld $5c
|
|
0a1d 005a ld $5a
|
|
0a1e 0058 ld $58
|
|
0a1f 0056 ld $56
|
|
0a20 0054 ld $54
|
|
0a21 0052 ld $52
|
|
0a22 0050 ld $50
|
|
0a23 004f ld $4f
|
|
0a24 004d ld $4d
|
|
0a25 004c ld $4c
|
|
0a26 004a ld $4a
|
|
0a27 0049 ld $49
|
|
0a28 0048 ld $48
|
|
0a29 0046 ld $46
|
|
0a2a 0045 ld $45
|
|
0a2b 0044 ld $44
|
|
0a2c 0043 ld $43
|
|
0a2d 0042 ld $42
|
|
0a2e 0041 ld $41
|
|
0a2f 0040 ld $40
|
|
0a30 003f ld $3f
|
|
0a31 003e ld $3e
|
|
0a32 003d ld $3d
|
|
0a33 003c ld $3c
|
|
0a34 003b ld $3b
|
|
0a35 003a ld $3a
|
|
0a36 0039 ld $39
|
|
0a37 0038 ld $38
|
|
0a38 0037 ld $37
|
|
0a39 0037 ld $37
|
|
0a3a 0036 ld $36
|
|
0a3b 0035 ld $35
|
|
0a3c 0034 ld $34
|
|
0a3d 0034 ld $34
|
|
0a3e 0033 ld $33
|
|
0a3f 0032 ld $32
|
|
0a40 0032 ld $32
|
|
0a41 0031 ld $31
|
|
0a42 0030 ld $30
|
|
0a43 0030 ld $30
|
|
0a44 002f ld $2f
|
|
0a45 002f ld $2f
|
|
0a46 002e ld $2e
|
|
0a47 002e ld $2e
|
|
0a48 002d ld $2d
|
|
0a49 002d ld $2d
|
|
0a4a 002c ld $2c
|
|
0a4b 002c ld $2c
|
|
0a4c 002b ld $2b
|
|
0a4d 002b ld $2b
|
|
0a4e 002a ld $2a
|
|
0a4f 002a ld $2a
|
|
0a50 0029 ld $29
|
|
0a51 0029 ld $29
|
|
0a52 0028 ld $28
|
|
0a53 0028 ld $28
|
|
0a54 0027 ld $27
|
|
0a55 0027 ld $27
|
|
0a56 0027 ld $27
|
|
0a57 0026 ld $26
|
|
0a58 0026 ld $26
|
|
0a59 0026 ld $26
|
|
0a5a 0025 ld $25
|
|
0a5b 0025 ld $25
|
|
0a5c 0024 ld $24
|
|
0a5d 0024 ld $24
|
|
0a5e 0024 ld $24
|
|
0a5f 0023 ld $23
|
|
0a60 0023 ld $23
|
|
0a61 0023 ld $23
|
|
0a62 0022 ld $22
|
|
0a63 0022 ld $22
|
|
0a64 0022 ld $22
|
|
0a65 0022 ld $22
|
|
0a66 0021 ld $21
|
|
0a67 0021 ld $21
|
|
0a68 0021 ld $21
|
|
0a69 0020 ld $20
|
|
0a6a 0020 ld $20
|
|
0a6b 0020 ld $20
|
|
0a6c 0020 ld $20
|
|
0a6d 001f ld $1f
|
|
0a6e 001f ld $1f
|
|
0a6f 001f ld $1f
|
|
0a70 001f ld $1f
|
|
0a71 001e ld $1e
|
|
0a72 001e ld $1e
|
|
0a73 001e ld $1e
|
|
0a74 001e ld $1e
|
|
0a75 001d ld $1d
|
|
0a76 001d ld $1d
|
|
0a77 001d ld $1d
|
|
0a78 001d ld $1d
|
|
0a79 001c ld $1c
|
|
0a7a 001c ld $1c
|
|
0a7b 001c ld $1c
|
|
* 5 times
|
|
0a7e 001b ld $1b
|
|
0a7f 001b ld $1b
|
|
0a80 001b ld $1b
|
|
* 5 times
|
|
0a83 001a ld $1a
|
|
0a84 001a ld $1a
|
|
0a85 001a ld $1a
|
|
* 5 times
|
|
0a88 0019 ld $19
|
|
0a89 0019 ld $19
|
|
0a8a 0019 ld $19
|
|
* 6 times
|
|
0a8e 0018 ld $18
|
|
0a8f 0018 ld $18
|
|
0a90 0018 ld $18
|
|
* 6 times
|
|
0a94 0017 ld $17
|
|
0a95 0017 ld $17
|
|
0a96 0017 ld $17
|
|
* 7 times
|
|
0a9b 0016 ld $16
|
|
0a9c 0016 ld $16
|
|
0a9d 0016 ld $16
|
|
* 8 times
|
|
0aa3 0015 ld $15
|
|
0aa4 0015 ld $15
|
|
0aa5 0015 ld $15
|
|
* 8 times
|
|
0aab 0014 ld $14
|
|
0aac 0014 ld $14
|
|
0aad 0014 ld $14
|
|
* 9 times
|
|
0ab4 0013 ld $13
|
|
0ab5 0013 ld $13
|
|
0ab6 0013 ld $13
|
|
* 9 times
|
|
0abd 0012 ld $12
|
|
0abe 0012 ld $12
|
|
0abf 0012 ld $12
|
|
* 11 times
|
|
0ac8 0011 ld $11
|
|
0ac9 0011 ld $11
|
|
0aca 0011 ld $11
|
|
* 12 times
|
|
0ad4 0010 ld $10
|
|
0ad5 0010 ld $10
|
|
0ad6 0010 ld $10
|
|
* 13 times
|
|
0ae1 000f ld $0f
|
|
0ae2 000f ld $0f
|
|
0ae3 000f ld $0f
|
|
* 16 times
|
|
0af1 000e ld $0e
|
|
0af2 000e ld $0e
|
|
0af3 000e ld $0e
|
|
* 10 times
|
|
2783
|
|
2784 trampoline()
|
|
0afb fe00 bra ac ;+-----------------------------------+
|
|
0afc fcfd bra $0afd ;| |
|
|
0afd 1404 ld $04,y ;| Trampoline for page $0a00 lookups |
|
|
0afe e068 jmp y,$68 ;| |
|
|
0aff c218 st [$18] ;+-----------------------------------+
|
|
2785
|
|
2786 #-----------------------------------------------------------------------
|
|
2787 #
|
|
2788 # $0d00 ROM page 11: More SYS functions
|
|
2789 #
|
|
2790 #-----------------------------------------------------------------------
|
|
2791
|
|
2792 align(0x100, size=0x100)
|
|
2793
|
|
2794 #-----------------------------------------------------------------------
|
|
2795 # Extension SYS_SetMode_v2_80
|
|
2796 #-----------------------------------------------------------------------
|
|
2797
|
|
2798 # Set video mode to 0 to 3 black scanlines per pixel line.
|
|
2799 #
|
|
2800 # Mainly for making the MODE command available in Tiny BASIC, so that
|
|
2801 # the user can experiment. It's adviced to refrain from using
|
|
2802 # SYS_SetMode_v2_80 in regular applications. Video mode is a deeply
|
|
2803 # personal preference, and the programmer shouldn't overrule the user
|
|
2804 # in that choice. The Gigatron philisophy is that the end user has
|
|
2805 # the final say on what happens on the system, not the application,
|
|
2806 # even if that implies a degraded performance. This doesn't mean that
|
|
2807 # all applications must work well in all video modes: mode 1 is still
|
|
2808 # the default. If an application really doesn't work at all in that
|
|
2809 # mode, it's acceptable to change mode once after loading.
|
|
2810 #
|
|
2811 # There's no "SYS_GetMode" function.
|
|
2812 #
|
|
2813 # Variables:
|
|
2814 # vAC bit 0:1 Mode:
|
|
2815 # 0 "ABCD" -> Full mode (slowest)
|
|
2816 # 1 "ABC-" -> Default mode after reset
|
|
2817 # 2 "A-C-" -> at67's mode
|
|
2818 # 3 "A---" -> HGM's mode
|
|
2819 # vAC bit 2:15 Ignored bits and should be 0
|
|
2820 #
|
|
2821 # Special values (ROM v4):
|
|
2822 # vAC = 1975 Zombie mode (no video signals, no input,
|
|
2823 # no blinkenlights).
|
|
2824 # vAC = -1 Leave zombie mode and restore previous mode.
|
|
2825
|
|
2826 # Actual duration is <80 cycles, but keep some room for future extensions
|
|
2827 label('SYS_SetMode_v2_80')
|
|
SYS_SetMode_v2_80:
|
|
0b00 140b ld $0b,y 2828 ld(hi('sys_SetMode'),Y) #15
|
|
0b01 e054 jmp y,$54 2829 jmp(Y,'sys_SetMode') #16
|
|
0b02 011e ld [$1e] 2830 ld([vReturn]) #17
|
|
2831
|
|
2832 #-----------------------------------------------------------------------
|
|
2833 # Extension SYS_SetMemory_v2_54
|
|
2834 #-----------------------------------------------------------------------
|
|
2835
|
|
2836 # SYS function for setting 1..256 bytes
|
|
2837 #
|
|
2838 # sysArgs[0] Copy count (in, changed)
|
|
2839 # sysArgs[1] Copy value (in)
|
|
2840 # sysArgs[2:3] Destination address (in, changed)
|
|
2841 #
|
|
2842 # Sets up to 8 bytes per invocation before restarting itself through vCPU.
|
|
2843 # Doesn't wrap around page boundary. Can run 3 times per 148-cycle time slice.
|
|
2844 # All combined that gives a 300% speedup over ROMv4 and before.
|
|
2845
|
|
2846 label('SYS_SetMemory_v2_54')
|
|
SYS_SetMemory_v2_54:
|
|
0b03 0124 ld [$24] 2847 ld([sysArgs+0]) #15
|
|
2848 bra('sys_SetMemory#18') #16
|
|
0b04 fc18 bra sys_SetMemory#18
|
|
0b05 1126 ld [$26],x 2849 ld([sysArgs+2],X) #17
|
|
2850
|
|
2851 #-----------------------------------------------------------------------
|
|
2852 # Extension SYS_SendSerial1_v3_80
|
|
2853 #-----------------------------------------------------------------------
|
|
2854
|
|
2855 # SYS function for sending data over serial controller port using
|
|
2856 # pulse width modulation of the vertical sync signal.
|
|
2857 #
|
|
2858 # Variables:
|
|
2859 # sysArgs[0:1] Source address (in, changed)
|
|
2860 # sysArgs[2] Start bit mask (typically 1) (in, changed)
|
|
2861 # sysArgs[3] Number of send frames X (in, changed)
|
|
2862 #
|
|
2863 # The sending will abort if input data is detected on the serial port.
|
|
2864 # Returns 0 in case of all bits sent, or <>0 in case of abort
|
|
2865 #
|
|
2866 # This modulates the next upcoming X vertical pulses with the supplied
|
|
2867 # data. A zero becomes a 7 line vPulse, a one will be 9 lines.
|
|
2868 # After that, the vPulse width falls back to 8 lines (idle).
|
|
2869
|
|
2870 label('SYS_SendSerial1_v3_80')
|
|
SYS_SendSerial1_v3_80:
|
|
0b06 0109 ld [$09] 2871 ld([videoY]) #15
|
|
2872 bra('sys_SendSerial1') #16
|
|
0b07 fc83 bra sys_SendSerial1
|
|
0b08 60b3 xora $b3 2873 xora(videoYline0) #17 First line of vertical blank
|
|
2874
|
|
2875 #-----------------------------------------------------------------------
|
|
2876 # Extension SYS_ExpanderControl_v4_40
|
|
2877 #-----------------------------------------------------------------------
|
|
2878
|
|
2879 # Sets the I/O and RAM expander's control register
|
|
2880 #
|
|
2881 # Variables:
|
|
2882 # vAC bit 2 Device enable /SS0
|
|
2883 # bit 3 Device enable /SS1
|
|
2884 # bit 4 Device enable /SS2
|
|
2885 # bit 5 Device enable /SS3
|
|
2886 # bit 6 Banking B0
|
|
2887 # bit 7 Banking B1
|
|
2888 # bit 15 Data out MOSI
|
|
2889 # sysArgs[7] Cache for control state (written to)
|
|
2890 #
|
|
2891 # Intended for prototyping, and probably too low-level for most applications
|
|
2892 # Still there's a safeguard: it's not possible to disable RAM using this
|
|
2893
|
|
2894 label('SYS_ExpanderControl_v4_40')
|
|
SYS_ExpanderControl_v4_40:
|
|
0b09 140c ld $0c,y 2895 ld(hi('sys_ExpanderControl'),Y) #15
|
|
0b0a e0fb jmp y,$fb 2896 jmp(Y,'sys_ExpanderControl') #16
|
|
0b0b 00fc ld $fc 2897 ld(0b11111100) #17 Safety (SCLK=0)
|
|
2898 # ^^^^^^^^
|
|
2899 # |||||||`-- SCLK
|
|
2900 # ||||||`--- Not connected
|
|
2901 # |||||`---- /SS0
|
|
2902 # ||||`----- /SS1
|
|
2903 # |||`------ /SS2
|
|
2904 # ||`------- /SS3
|
|
2905 # |`-------- B0
|
|
2906 # `--------- B1
|
|
2907
|
|
2908 #-----------------------------------------------------------------------
|
|
2909 # Extension SYS_Run6502_v4_80
|
|
2910 #-----------------------------------------------------------------------
|
|
2911
|
|
2912 # Transfer control to v6502
|
|
2913 #
|
|
2914 # Calling 6502 code from vCPU goes (only) through this SYS function.
|
|
2915 # Directly modifying the vCpuSelect variable is unreliable. The
|
|
2916 # control transfer is immediate, without waiting for the current
|
|
2917 # time slice to end or first returning to vCPU.
|
|
2918 #
|
|
2919 # vCPU code and v6502 code can interoperate without much hassle:
|
|
2920 # - The v6502 program counter is vLR, and v6502 doesn't touch vPC
|
|
2921 # - Returning to vCPU is with the BRK instruction
|
|
2922 # - BRK doesn't dump process state on the stack
|
|
2923 # - vCPU can save/restore the vLR with PUSH/POP
|
|
2924 # - Stacks are shared, vAC is shared
|
|
2925 # - vAC can indicate what the v6502 code wants. vAC+1 will be cleared
|
|
2926 # - Alternative is to leave a word in sysArgs[6:7] (v6502 X and Y registers)
|
|
2927 # - Another way is to set vPC before BRK, and vCPU will continue there(+2)
|
|
2928 #
|
|
2929 # Calling v6502 code from vCPU looks like this:
|
|
2930 # LDWI SYS_Run6502_v4_80
|
|
2931 # STW sysFn
|
|
2932 # LDWI $6502_start_address
|
|
2933 # STW vLR
|
|
2934 # SYS 80
|
|
2935 #
|
|
2936 # Variables:
|
|
2937 # vAC Accumulator
|
|
2938 # vLR Program Counter
|
|
2939 # vSP Stack Pointer (+1)
|
|
2940 # sysArgs[6] Index Register X
|
|
2941 # sysArgs[7] Index Register Y
|
|
2942 # For info:
|
|
2943 # sysArgs[0:1] Address Register, free to clobber
|
|
2944 # sysArgs[2] Instruction Register, free to clobber
|
|
2945 # sysArgs[3:5] Flags, don't touch
|
|
2946 #
|
|
2947 # Implementation details::
|
|
2948 #
|
|
2949 # The time to reserve for this transition is the maximum time
|
|
2950 # between NEXT and v6502_check. This is
|
|
2951 # SYS call duration + 2*v6502_maxTicks + (v6502_overhead - vCPU_overhead)
|
|
2952 # = 22 + 28 + (11 - 9) = 62 cycles.
|
|
2953 # So reserving 80 cycles is future proof. This isn't overhead, as it includes
|
|
2954 # the fetching of the first 6502 opcode and its operands..
|
|
2955 #
|
|
2956 # 0 10 28=0 9
|
|
2957 # ---+----+---------+------------+------------------+-----------+---
|
|
2958 # video | nop| runVcpu | ENTER | At least one ins | EXIT | video
|
|
2959 # ---+----+---------+------------+------------------+-----------+---
|
|
2960 # sync prelude ENTER-to-ins ins-to-NEXT NEXT-to-video
|
|
2961 # |<-->|
|
|
2962 # 0/1 |<------->|
|
|
2963 # 5 |<----------------------------->|
|
|
2964 # runVCpu_overhead 28 |<--------->|
|
|
2965 # 2*maxTicks 9
|
|
2966 # vCPU_overhead
|
|
2967 #
|
|
2968 # 0 21 38=0 11
|
|
2969 # ---+----+---------+----------------+--------------------+-----------+---
|
|
2970 # video | nop| runVcpu | v6502_ENTER | At least one fetch |v6502_exitB| video
|
|
2971 # ---+----+---------+----------------+--------------------+-----------+---
|
|
2972 # sync prelude enter-to-fetch fetch-to-check check-to-video
|
|
2973 # |<-->|
|
|
2974 # 0/1 |<------->|
|
|
2975 # 5 |<----------------------------------->|
|
|
2976 # runVcpu_overhead 38 |<--------->|
|
|
2977 # 2*v6520_maxTicks 11
|
|
2978 # v6502_overhead
|
|
2979
|
|
2980 label('SYS_Run6502_v4_80')
|
|
SYS_Run6502_v4_80:
|
|
0b0c 140d ld $0d,y 2981 ld(hi('sys_v6502'),Y) #15
|
|
0b0d e07f jmp y,$7f 2982 jmp(Y,'sys_v6502') #16
|
|
0b0e 000d ld $0d 2983 ld(hi('v6502_ENTER')) #17 Activate v6502
|
|
2984
|
|
2985 #-----------------------------------------------------------------------
|
|
2986 # Extension SYS_ResetWaveforms_v4_50
|
|
2987 #-----------------------------------------------------------------------
|
|
2988
|
|
2989 # soundTable[4x+0] = sawtooth, to be modified into metallic/noise
|
|
2990 # soundTable[4x+1] = pulse
|
|
2991 # soundTable[4x+2] = triangle
|
|
2992 # soundTable[4x+3] = sawtooth, also useful to right shift 2 bits
|
|
2993
|
|
2994 label('SYS_ResetWaveforms_v4_50')
|
|
SYS_ResetWaveforms_v4_50:
|
|
0b0f 1412 ld $12,y 2995 ld(hi('sys_ResetWaveforms'),Y) #15 Initial setup of waveforms. [vAC+0]=i
|
|
0b10 e0ae jmp y,$ae 2996 jmp(Y,'sys_ResetWaveforms') #16
|
|
0b11 1407 ld $07,y 2997 ld(soundTable>>8,Y) #17
|
|
2998
|
|
2999 #-----------------------------------------------------------------------
|
|
3000 # Extension SYS_ShuffleNoise_v4_46
|
|
3001 #-----------------------------------------------------------------------
|
|
3002
|
|
3003 # Use simple 6-bits variation of RC4 to permutate waveform 0 in soundTable
|
|
3004
|
|
3005 label('SYS_ShuffleNoise_v4_46')
|
|
SYS_ShuffleNoise_v4_46:
|
|
0b12 1412 ld $12,y 3006 ld(hi('sys_ShuffleNoise'),Y) #15 Shuffle soundTable[4i+0]. [vAC+0]=4j, [vAC+1]=4i
|
|
0b13 e0cf jmp y,$cf 3007 jmp(Y,'sys_ShuffleNoise') #16
|
|
0b14 1407 ld $07,y 3008 ld(soundTable>>8,Y) #17
|
|
3009
|
|
3010 #-----------------------------------------------------------------------
|
|
3011 # Extension SYS_SpiExchangeBytes_v4_134
|
|
3012 #-----------------------------------------------------------------------
|
|
3013
|
|
3014 # Send AND receive 1..256 bytes over SPI interface
|
|
3015
|
|
3016 # Variables:
|
|
3017 # sysArgs[0] Page index start, for both send/receive (in, changed)
|
|
3018 # sysArgs[1] Memory page for send data (in)
|
|
3019 # sysArgs[2] Page index stop (in)
|
|
3020 # sysArgs[3] Memory page for receive data (in)
|
|
3021 # sysArgs[4] Scratch (changed)
|
|
3022
|
|
3023 label('SYS_SpiExchangeBytes_v4_134')
|
|
SYS_SpiExchangeBytes_v4_134:
|
|
0b15 140d ld $0d,y 3024 ld(hi('sys_SpiExchangeBytes'),Y)#15
|
|
0b16 e009 jmp y,$09 3025 jmp(Y,'sys_SpiExchangeBytes') #16
|
|
0b17 1401 ld $01,y 3026 ld(hi(ctrlBits),Y) #17 Control state as saved by SYS_ExpanderControl
|
|
3027
|
|
3028 #-----------------------------------------------------------------------
|
|
3029 # Implementations
|
|
3030 #-----------------------------------------------------------------------
|
|
3031
|
|
3032 # SYS_SetMemory_54 implementation
|
|
3033 label('sys_SetMemory#18')
|
|
sys_SetMemory#18:
|
|
0b18 1527 ld [$27],y 3034 ld([sysArgs+3],Y) #18
|
|
0b19 f83c ble .sysSb#21 3035 ble('.sysSb#21') #19 Enter fast lane if >=128 or at 0 (-> 256)
|
|
0b1a a008 suba $08 3036 suba(8) #20
|
|
0b1b f43e bge .sysSb#23 3037 bge('.sysSb#23') #21 Or when >=8
|
|
0b1c c224 st [$24] 3038 st([sysArgs+0]) #22
|
|
0b1d 2004 anda $04 3039 anda(4) #23
|
|
0b1e f025 beq .sysSb#26 3040 beq('.sysSb#26') #24
|
|
0b1f 0125 ld [$25] 3041 ld([sysArgs+1]) #25 Set 4 pixels
|
|
0b20 de00 st [y,x++] 3042 st([Y,Xpp]) #26
|
|
0b21 de00 st [y,x++] 3043 st([Y,Xpp]) #27
|
|
0b22 de00 st [y,x++] 3044 st([Y,Xpp]) #28
|
|
0b23 fc28 bra .sysSb#31 3045 bra('.sysSb#31') #29
|
|
0b24 de00 st [y,x++] 3046 st([Y,Xpp]) #30
|
|
3047 label('.sysSb#26')
|
|
.sysSb#26: 0b25 0001 ld $01 3048 wait(31-26) #26
|
|
0b26 ec26 bne $0b26
|
|
0b27 a001 suba $01
|
|
3049 label('.sysSb#31')
|
|
.sysSb#31: 0b28 0124 ld [$24] 3050 ld([sysArgs+0]) #31
|
|
0b29 2002 anda $02 3051 anda(2) #32
|
|
0b2a f02f beq .sysSb#35 3052 beq('.sysSb#35') #33
|
|
0b2b 0125 ld [$25] 3053 ld([sysArgs+1]) #34 Set 2 pixels
|
|
0b2c de00 st [y,x++] 3054 st([Y,Xpp]) #35
|
|
0b2d fc32 bra .sysSb#38 3055 bra('.sysSb#38') #36
|
|
0b2e de00 st [y,x++] 3056 st([Y,Xpp]) #37
|
|
3057 label('.sysSb#35')
|
|
.sysSb#35: 0b2f 0200 nop 3058 wait(38-35) #35
|
|
0b30 0200 nop
|
|
0b31 0200 nop
|
|
3059 label('.sysSb#38')
|
|
.sysSb#38: 0b32 0124 ld [$24] 3060 ld([sysArgs+0]) #38
|
|
0b33 2001 anda $01 3061 anda(1) #39
|
|
0b34 f037 beq $0b37 3062 beq(pc()+3) #40
|
|
0b35 fc38 bra $0b38 3063 bra(pc()+3) #41
|
|
0b36 0125 ld [$25] 3064 ld([sysArgs+1]) #42 Set 1 pixel
|
|
0b37 0d00 ld [y,x] 3065 ld([Y,X]) #42(!) No change
|
|
0b38 ce00 st [y,x] 3066 st([Y,X]) #43
|
|
0b39 1403 ld $03,y 3067 ld(hi('NEXTY'),Y) #44 Return
|
|
0b3a e000 jmp y,$00 3068 jmp(Y,'NEXTY') #45 All done
|
|
0b3b 00e8 ld $e8 3069 ld(-48/2) #46
|
|
3070 label('.sysSb#21')
|
|
.sysSb#21: 0b3c 0200 nop 3071 nop() #21
|
|
0b3d c224 st [$24] 3072 st([sysArgs+0]) #22
|
|
3073 label('.sysSb#23')
|
|
.sysSb#23: 0b3e 0125 ld [$25] 3074 ld([sysArgs+1]) #23 Set 8 pixels
|
|
0b3f de00 st [y,x++] 3075 st([Y,Xpp]) #24
|
|
0b40 de00 st [y,x++] 3076 st([Y,Xpp]) #25
|
|
0b41 de00 st [y,x++] 3077 st([Y,Xpp]) #26
|
|
0b42 de00 st [y,x++] 3078 st([Y,Xpp]) #27
|
|
0b43 de00 st [y,x++] 3079 st([Y,Xpp]) #28
|
|
0b44 de00 st [y,x++] 3080 st([Y,Xpp]) #29
|
|
0b45 de00 st [y,x++] 3081 st([Y,Xpp]) #30
|
|
0b46 de00 st [y,x++] 3082 st([Y,Xpp]) #31
|
|
0b47 0126 ld [$26] 3083 ld([sysArgs+2]) #32 Advance write pointer
|
|
0b48 8008 adda $08 3084 adda(8) #33
|
|
0b49 c226 st [$26] 3085 st([sysArgs+2]) #34
|
|
0b4a 0124 ld [$24] 3086 ld([sysArgs+0]) #35
|
|
0b4b f04e beq $0b4e 3087 beq(pc()+3) #36
|
|
0b4c fc4f bra $0b4f 3088 bra(pc()+3) #37
|
|
0b4d 00fe ld $fe 3089 ld(-2) #38 Self-restart when more to do
|
|
0b4e 0000 ld $00 3090 ld(0) #38(!)
|
|
0b4f 8116 adda [$16] 3091 adda([vPC]) #39
|
|
0b50 c216 st [$16] 3092 st([vPC]) #40
|
|
0b51 1403 ld $03,y 3093 ld(hi('REENTER'),Y) #41
|
|
0b52 e0cb jmp y,$cb 3094 jmp(Y,'REENTER') #42
|
|
0b53 00e9 ld $e9 3095 ld(-46/2) #43
|
|
3096
|
|
3097 # SYS_SetMode_80 implementation
|
|
3098 label('sys_SetMode')
|
|
sys_SetMode: 0b54 ec57 bne $0b57 3099 bne(pc()+3) #18
|
|
0b55 fc57 bra $0b57 3100 bra(pc()+2) #19
|
|
0b56 0003 ld $03 3101 ld('startVideo') #20 First enable video if disabled
|
|
0b57 c21e st [$1e] 3102 st([vReturn]) #20,21
|
|
0b58 0119 ld [$19] 3103 ld([vAC+1]) #22
|
|
0b59 f063 beq .sysSm#25 3104 beq('.sysSm#25') #23
|
|
0b5a 1403 ld $03,y 3105 ld(hi('REENTER'),Y) #24
|
|
0b5b 6118 xora [$18] 3106 xora([vAC]) #25
|
|
0b5c 60b0 xora $b0 3107 xora((1975>>8)^(1975&255)) #26 Poor man\'s 1975 detection
|
|
0b5d ec60 bne $0b60 3108 bne(pc()+3) #27
|
|
0b5e fc61 bra $0b61 3109 bra(pc()+3) #28
|
|
3110 assert videoZ == 0x0100
|
|
0b5f c21e st [$1e] 3111 st([vReturn]) #29 DISABLE video/audio/serial/etc
|
|
0b60 0200 nop 3112 nop() #29(!) Ignore and return
|
|
0b61 e0cb jmp y,$cb 3113 jmp(Y,'REENTER') #30
|
|
0b62 00ef ld $ef 3114 ld(-34/2) #31
|
|
3115 label('.sysSm#25')
|
|
.sysSm#25: 0b63 0118 ld [$18] 3116 ld([vAC]) #25 Mode 0,1,2,3
|
|
0b64 2003 anda $03 3117 anda(3) #26
|
|
0b65 8068 adda $68 3118 adda('.sysSm#30') #27
|
|
0b66 fe00 bra ac 3119 bra(AC) #28
|
|
0b67 fc6c bra .sysSm#31 3120 bra('.sysSm#31') #29
|
|
3121 label('.sysSm#30')
|
|
.sysSm#30: 0b68 000a ld $0a 3122 ld('pixels') #30 videoB lines
|
|
0b69 000a ld $0a 3123 ld('pixels') #30
|
|
0b6a 00f6 ld $f6 3124 ld('nopixels') #30
|
|
0b6b 00f6 ld $f6 3125 ld('nopixels') #30
|
|
3126 label('.sysSm#31')
|
|
.sysSm#31: 0b6c c20a st [$0a] 3127 st([videoModeB]) #31
|
|
0b6d 0118 ld [$18] 3128 ld([vAC]) #32
|
|
0b6e 2003 anda $03 3129 anda(3) #33
|
|
0b6f 8072 adda $72 3130 adda('.sysSm#37') #34
|
|
0b70 fe00 bra ac 3131 bra(AC) #35
|
|
0b71 fc76 bra .sysSm#38 3132 bra('.sysSm#38') #36
|
|
3133 label('.sysSm#37')
|
|
.sysSm#37: 0b72 000a ld $0a 3134 ld('pixels') #37 videoC lines
|
|
0b73 000a ld $0a 3135 ld('pixels') #37
|
|
0b74 000a ld $0a 3136 ld('pixels') #37
|
|
0b75 00f6 ld $f6 3137 ld('nopixels') #37
|
|
3138 label('.sysSm#38')
|
|
.sysSm#38: 0b76 c20b st [$0b] 3139 st([videoModeC]) #38
|
|
0b77 0118 ld [$18] 3140 ld([vAC]) #39
|
|
0b78 2003 anda $03 3141 anda(3) #40
|
|
0b79 807c adda $7c 3142 adda('.sysSm#44') #41
|
|
0b7a fe00 bra ac 3143 bra(AC) #42
|
|
0b7b fc80 bra .sysSm#45 3144 bra('.sysSm#45') #43
|
|
3145 label('.sysSm#44')
|
|
.sysSm#44: 0b7c 000a ld $0a 3146 ld('pixels') #44 videoD lines
|
|
0b7d 00f6 ld $f6 3147 ld('nopixels') #44
|
|
0b7e 00f6 ld $f6 3148 ld('nopixels') #44
|
|
0b7f 00f6 ld $f6 3149 ld('nopixels') #44
|
|
3150 label('.sysSm#45')
|
|
.sysSm#45: 0b80 c20c st [$0c] 3151 st([videoModeD]) #45
|
|
0b81 e0cb jmp y,$cb 3152 jmp(Y,'REENTER') #46
|
|
0b82 00e7 ld $e7 3153 ld(-50/2) #47
|
|
3154
|
|
3155 # SYS_SendSerial1_v3_80 implementation
|
|
3156 label('sys_SendSerial1')
|
|
sys_SendSerial1:
|
|
0b83 f08a beq .sysSs#20 3157 beq('.sysSs#20') #18
|
|
0b84 1124 ld [$24],x 3158 ld([sysArgs+0],X) #19
|
|
0b85 0116 ld [$16] 3159 ld([vPC]) #20 Wait for vBlank
|
|
0b86 a002 suba $02 3160 suba(2) #21
|
|
0b87 1403 ld $03,y 3161 ld(hi('REENTER_28'),Y) #22
|
|
0b88 e0ca jmp y,$ca 3162 jmp(Y,'REENTER_28') #23
|
|
0b89 c216 st [$16] 3163 st([vPC]) #24
|
|
3164 label('.sysSs#20')
|
|
.sysSs#20: 0b8a 1525 ld [$25],y 3165 ld([sysArgs+1],Y) #20 Synchronized with vBlank
|
|
0b8b 0d00 ld [y,x] 3166 ld([Y,X]) #21 Copy next bit
|
|
0b8c 2126 anda [$26] 3167 anda([sysArgs+2]) #22
|
|
0b8d ec90 bne $0b90 3168 bne(pc()+3) #23
|
|
0b8e fc91 bra $0b91 3169 bra(pc()+3) #24
|
|
0b8f 000e ld $0e 3170 ld(7*2) #25
|
|
0b90 0012 ld $12 3171 ld(9*2) #25
|
|
0b91 c20d st [$0d] 3172 st([videoPulse]) #26
|
|
0b92 0126 ld [$26] 3173 ld([sysArgs+2]) #27 Rotate input bit
|
|
0b93 8200 adda ac 3174 adda(AC) #28
|
|
0b94 ec97 bne $0b97 3175 bne(pc()+3) #29
|
|
0b95 fc97 bra $0b97 3176 bra(pc()+2) #30
|
|
0b96 0001 ld $01 3177 ld(1) #31
|
|
0b97 c226 st [$26] 3178 st([sysArgs+2]) #31,32 (must be idempotent)
|
|
0b98 2001 anda $01 3179 anda(1) #33 Optionally increment pointer
|
|
0b99 8124 adda [$24] 3180 adda([sysArgs+0]) #34
|
|
0b9a d224 st [$24],x 3181 st([sysArgs+0],X) #35
|
|
0b9b 0127 ld [$27] 3182 ld([sysArgs+3]) #36 Frame counter
|
|
0b9c a001 suba $01 3183 suba(1) #37
|
|
0b9d f0ac beq .sysSs#40 3184 beq('.sysSs#40') #38
|
|
0b9e 1403 ld $03,y 3185 ld(hi('REENTER'),Y) #39
|
|
0b9f c227 st [$27] 3186 st([sysArgs+3]) #40
|
|
0ba0 010f ld [$0f] 3187 ld([serialRaw]) #41 Test for anything being sent back
|
|
0ba1 60ff xora $ff 3188 xora(255) #42
|
|
0ba2 f0a7 beq .sysSs#45 3189 beq('.sysSs#45') #43
|
|
0ba3 c218 st [$18] 3190 st([vAC]) #44 Abort after key press with non-zero error
|
|
0ba4 c219 st [$19] 3191 st([vAC+1]) #45
|
|
0ba5 e0cb jmp y,$cb 3192 jmp(Y,'REENTER') #46
|
|
0ba6 00e7 ld $e7 3193 ld(-50/2) #47
|
|
3194 label('.sysSs#45')
|
|
.sysSs#45: 0ba7 0116 ld [$16] 3195 ld([vPC]) #45 Continue sending bits
|
|
0ba8 a002 suba $02 3196 suba(2) #46
|
|
0ba9 c216 st [$16] 3197 st([vPC]) #47
|
|
0baa e0cb jmp y,$cb 3198 jmp(Y,'REENTER') #48
|
|
0bab 00e6 ld $e6 3199 ld(-52/2) #49
|
|
3200 label('.sysSs#40')
|
|
.sysSs#40: 0bac c218 st [$18] 3201 st([vAC]) #40 Stop sending bits, no error
|
|
0bad c219 st [$19] 3202 st([vAC+1]) #41
|
|
0bae e0cb jmp y,$cb 3203 jmp(Y,'REENTER') #42
|
|
0baf 00e9 ld $e9 3204 ld(-46/2) #43
|
|
3205
|
|
3206 # CALLI implementation (vCPU instruction)
|
|
3207 label('calli#13')
|
|
calli#13: 0bb0 8003 adda $03 3208 adda(3) #13,43
|
|
0bb1 c21a st [$1a] 3209 st([vLR]) #14
|
|
0bb2 0117 ld [$17] 3210 ld([vPC+1]) #15
|
|
0bb3 d61b st [$1b],y 3211 st([vLR+1],Y) #16
|
|
0bb4 0d00 ld [y,x] 3212 ld([Y,X]) #17
|
|
0bb5 de00 st [y,x++] 3213 st([Y,Xpp]) #18 Just X++
|
|
0bb6 a002 suba $02 3214 suba(2) #19
|
|
0bb7 c216 st [$16] 3215 st([vPC]) #20
|
|
0bb8 0d00 ld [y,x] 3216 ld([Y,X]) #21
|
|
0bb9 1403 ld $03,y 3217 ld(hi('REENTER_28'),Y) #22
|
|
0bba e0ca jmp y,$ca 3218 jmp(Y,'REENTER_28') #23
|
|
0bbb c217 st [$17] 3219 st([vPC+1]) #24
|
|
3220
|
|
3221 # -------------------------------------------------------------
|
|
3222 # vCPU instructions for comparisons between two 16-bit operands
|
|
3223 # -------------------------------------------------------------
|
|
3224 #
|
|
3225 # vCPU's conditional branching (BCC) always compares vAC against 0,
|
|
3226 # treating vAC as a two's complement 16-bit number. When we need to
|
|
3227 # compare two arbitrary numnbers we normally first take their difference
|
|
3228 # with SUBW. However, when this difference is too large, the subtraction
|
|
3229 # overflows and we get the wrong outcome. To get it right over the
|
|
3230 # entire range, an elaborate sequence is needed. TinyBASIC uses this
|
|
3231 # blurp for its relational operators. (It compares stack variable $02
|
|
3232 # with zero page variable $3a.)
|
|
3233 #
|
|
3234 # 0461 ee 02 LDLW $02
|
|
3235 # 0463 fc 3a XORW $3a
|
|
3236 # 0465 35 53 6a BGE $046c
|
|
3237 # 0468 ee 02 LDLW $02
|
|
3238 # 046a 90 6e BRA $0470
|
|
3239 # 046c ee 02 LDLW $02
|
|
3240 # 046e b8 3a SUBW $3a
|
|
3241 # 0470 35 56 73 BLE $0475
|
|
3242 #
|
|
3243 # The CMPHS and CMPHU instructions were introduced to simplify this.
|
|
3244 # They inspect both operands to see if there is an overflow risk. If
|
|
3245 # so, they modify vAC such that their difference gets smaller, while
|
|
3246 # preserving the relation between the two operands. After that, the
|
|
3247 # SUBW instruction can't overflow and we achieve a correct comparison.
|
|
3248 # Use CMPHS for signed comparisons and CMPHU for unsigned. With these,
|
|
3249 # the sequence above becomes:
|
|
3250 #
|
|
3251 # 0461 ee 02 LDLW $02
|
|
3252 # 0463 1f 3b CMPHS $3b Note: high byte of operand
|
|
3253 # 0465 b8 3a SUBW $3a
|
|
3254 # 0467 35 56 73 BLE $0475
|
|
3255 #
|
|
3256 # CMPHS/CMPHU don't make much sense other than in combination with
|
|
3257 # SUBW. These modify vACH, if needed, as given in the following table:
|
|
3258 #
|
|
3259 # vACH varH | vACH
|
|
3260 # bit7 bit7 | CMPHS CMPHU
|
|
3261 # ---------------------------
|
|
3262 # 0 0 | vACH vACH no change needed
|
|
3263 # 0 1 | varH+1 varH-1 narrowing the range
|
|
3264 # 1 0 | varH-1 varH+1 narrowing the range
|
|
3265 # 1 1 | vACH vACH no change needed
|
|
3266 # ---------------------------
|
|
3267
|
|
3268 # CMPHS implementation (vCPU instruction)
|
|
3269 label('cmphs#13')
|
|
cmphs#13: 0bbc 1403 ld $03,y 3270 ld(hi('REENTER'),Y) #13
|
|
0bbd 0500 ld [x] 3271 ld([X]) #14
|
|
0bbe 6119 xora [$19] 3272 xora([vAC+1]) #15
|
|
0bbf f4d0 bge .cmphu#18 3273 bpl('.cmphu#18') #16 Skip if same sign
|
|
0bc0 0119 ld [$19] 3274 ld([vAC+1]) #17
|
|
0bc1 e8c4 blt $0bc4 3275 bmi(pc()+3) #18
|
|
0bc2 fcc5 bra .cmphs#21 3276 bra(pc()+3) #19
|
|
3277 label('.cmphs#20')
|
|
.cmphs#20: 0bc3 0001 ld $01 3278 ld(+1) #20 vAC < variable
|
|
0bc4 00ff ld $ff 3279 ld(-1) #20(!) vAC > variable
|
|
3280 label('.cmphs#21')
|
|
.cmphs#21: 0bc5 8500 adda [x] 3281 adda([X]) #21
|
|
0bc6 c219 st [$19] 3282 st([vAC+1]) #22
|
|
0bc7 e0ca jmp y,$ca 3283 jmp(Y,'REENTER_28') #23
|
|
3284 #dummy() #24 Overlap
|
|
3285 #
|
|
3286 # CMPHS implementation (vCPU instruction)
|
|
3287 label('cmphu#13')
|
|
cmphu#13: 0bc8 1403 ld $03,y 3288 ld(hi('REENTER'),Y) #13,24
|
|
0bc9 0500 ld [x] 3289 ld([X]) #14
|
|
0bca 6119 xora [$19] 3290 xora([vAC+1]) #15
|
|
0bcb f4d0 bge .cmphu#18 3291 bpl('.cmphu#18') #16 Skip if same sign
|
|
0bcc 0119 ld [$19] 3292 ld([vAC+1]) #17
|
|
0bcd e8c3 blt .cmphs#20 3293 bmi('.cmphs#20') #18
|
|
0bce fcc5 bra .cmphs#21 3294 bra('.cmphs#21') #19
|
|
0bcf 00ff ld $ff 3295 ld(-1) #20 vAC > variable
|
|
3296
|
|
3297 # No-operation for CMPHS/CMPHU when high bits are equal
|
|
3298 label('.cmphu#18')
|
|
.cmphu#18: 0bd0 e0cb jmp y,$cb 3299 jmp(Y,'REENTER') #18
|
|
0bd1 00f5 ld $f5 3300 ld(-22/2) #19
|
|
3301
|
|
3302 #-----------------------------------------------------------------------
|
|
3303 #
|
|
3304 # $0c00 ROM page 12: More SYS functions (sprites)
|
|
3305 #
|
|
3306 # Page 1: vertical blank interval
|
|
3307 # Page 2: visible scanlines
|
|
3308 #
|
|
3309 #-----------------------------------------------------------------------
|
|
3310
|
|
0bd2 0200 nop 3311 align(0x100, size=0x100)
|
|
0bd3 0200 nop
|
|
0bd4 0200 nop
|
|
* 46 times
|
|
3312
|
|
3313 #-----------------------------------------------------------------------
|
|
3314 # Extension SYS_Sprite6_v3_64
|
|
3315 # Extension SYS_Sprite6x_v3_64
|
|
3316 # Extension SYS_Sprite6y_v3_64
|
|
3317 # Extension SYS_Sprite6xy_v3_64
|
|
3318 #-----------------------------------------------------------------------
|
|
3319
|
|
3320 # Blit sprite in screen memory
|
|
3321 #
|
|
3322 # Variables
|
|
3323 # vAC Destination address in screen
|
|
3324 # sysArgs[0:1] Source address of 6xY pixels (colors 0..63) terminated
|
|
3325 # by negative byte value N (typically N = -Y)
|
|
3326 # sysArgs[2:7] Scratch (user as copy buffer)
|
|
3327 #
|
|
3328 # This SYS function draws a sprite of 6 pixels wide and Y pixels high.
|
|
3329 # The pixel data is read sequentually from RAM, in horizontal chunks
|
|
3330 # of 6 pixels at a time, and then written to the screen through the
|
|
3331 # destination pointer (each chunk underneath the previous), thus
|
|
3332 # drawing a 6xY stripe. Pixel values should be non-negative. The first
|
|
3333 # negative byte N after a chunk signals the end of the sprite data.
|
|
3334 # So the sprite's height Y is determined by the source data and is
|
|
3335 # therefore flexible. This negative byte value, typically N == -Y,
|
|
3336 # is then used to adjust the destination pointer's high byte, to make
|
|
3337 # it easier to draw sprites wider than 6 pixels: just repeat the SYS
|
|
3338 # call for as many 6-pixel wide stripes you need. All arguments are
|
|
3339 # already left in place to facilitate this. After one call, the source
|
|
3340 # pointer will point past that source data, effectively:
|
|
3341 # src += Y * 6 + 1
|
|
3342 # The destination pointer will have been adjusted as:
|
|
3343 # dst += (Y + N) * 256 + 6
|
|
3344 # (With arithmetic wrapping around on the same memory page)
|
|
3345 #
|
|
3346 # Y is only limited by source memory, not by CPU cycles. The
|
|
3347 # implementation is such that the SYS function self-repeats, each
|
|
3348 # time drawing the next 6-pixel chunk. It can typically draw 12
|
|
3349 # pixels per scanline this way.
|
|
3350
|
|
3351 label('SYS_Sprite6_v3_64')
|
|
3352
|
|
SYS_Sprite6_v3_64:
|
|
0c00 1124 ld [$24],x 3353 ld([sysArgs+0],X) #15 Pixel data source address
|
|
0c01 1525 ld [$25],y 3354 ld([sysArgs+1],Y) #16
|
|
0c02 0d00 ld [y,x] 3355 ld([Y,X]) #17 Next pixel or stop
|
|
0c03 f411 bge .sysDpx0 3356 bpl('.sysDpx0') #18
|
|
0c04 de00 st [y,x++] 3357 st([Y,Xpp]) #19 Just X++
|
|
3358
|
|
0c05 8119 adda [$19] 3359 adda([vAC+1]) #20 Adjust dst for convenience
|
|
0c06 c219 st [$19] 3360 st([vAC+1]) #21
|
|
0c07 0118 ld [$18] 3361 ld([vAC]) #22
|
|
0c08 8006 adda $06 3362 adda(6) #23
|
|
0c09 c218 st [$18] 3363 st([vAC]) #24
|
|
0c0a 0124 ld [$24] 3364 ld([sysArgs+0]) #25 Adjust src for convenience
|
|
0c0b 8001 adda $01 3365 adda(1) #26
|
|
0c0c c224 st [$24] 3366 st([sysArgs+0]) #27
|
|
0c0d 0200 nop 3367 nop() #28
|
|
0c0e 1403 ld $03,y 3368 ld(hi('REENTER'),Y) #29 Normal exit (no self-repeat)
|
|
0c0f e0cb jmp y,$cb 3369 jmp(Y,'REENTER') #30
|
|
0c10 00ef ld $ef 3370 ld(-34/2) #31
|
|
3371
|
|
3372 label('.sysDpx0')
|
|
.sysDpx0: 0c11 c226 st [$26] 3373 st([sysArgs+2]) #20 Gobble 6 pixels into buffer
|
|
0c12 0d00 ld [y,x] 3374 ld([Y,X]) #21
|
|
0c13 de00 st [y,x++] 3375 st([Y,Xpp]) #22 Just X++
|
|
0c14 c227 st [$27] 3376 st([sysArgs+3]) #23
|
|
0c15 0d00 ld [y,x] 3377 ld([Y,X]) #24
|
|
0c16 de00 st [y,x++] 3378 st([Y,Xpp]) #25 Just X++
|
|
0c17 c228 st [$28] 3379 st([sysArgs+4]) #26
|
|
0c18 0d00 ld [y,x] 3380 ld([Y,X]) #27
|
|
0c19 de00 st [y,x++] 3381 st([Y,Xpp]) #28 Just X++
|
|
0c1a c229 st [$29] 3382 st([sysArgs+5]) #29
|
|
0c1b 0d00 ld [y,x] 3383 ld([Y,X]) #30
|
|
0c1c de00 st [y,x++] 3384 st([Y,Xpp]) #31 Just X++
|
|
0c1d c22a st [$2a] 3385 st([sysArgs+6]) #32
|
|
0c1e 0d00 ld [y,x] 3386 ld([Y,X]) #33
|
|
0c1f de00 st [y,x++] 3387 st([Y,Xpp]) #34 Just X++
|
|
0c20 c22b st [$2b] 3388 st([sysArgs+7]) #35
|
|
3389
|
|
0c21 1118 ld [$18],x 3390 ld([vAC],X) #36 Screen memory destination address
|
|
0c22 1519 ld [$19],y 3391 ld([vAC+1],Y) #37
|
|
0c23 0126 ld [$26] 3392 ld([sysArgs+2]) #38 Write 6 pixels
|
|
0c24 de00 st [y,x++] 3393 st([Y,Xpp]) #39
|
|
0c25 0127 ld [$27] 3394 ld([sysArgs+3]) #40
|
|
0c26 de00 st [y,x++] 3395 st([Y,Xpp]) #41
|
|
0c27 0128 ld [$28] 3396 ld([sysArgs+4]) #42
|
|
0c28 de00 st [y,x++] 3397 st([Y,Xpp]) #43
|
|
0c29 0129 ld [$29] 3398 ld([sysArgs+5]) #44
|
|
0c2a de00 st [y,x++] 3399 st([Y,Xpp]) #45
|
|
0c2b 012a ld [$2a] 3400 ld([sysArgs+6]) #46
|
|
0c2c de00 st [y,x++] 3401 st([Y,Xpp]) #47
|
|
0c2d 012b ld [$2b] 3402 ld([sysArgs+7]) #48
|
|
0c2e de00 st [y,x++] 3403 st([Y,Xpp]) #49
|
|
3404
|
|
0c2f 0124 ld [$24] 3405 ld([sysArgs+0]) #50 src += 6
|
|
0c30 8006 adda $06 3406 adda(6) #51
|
|
0c31 c224 st [$24] 3407 st([sysArgs+0]) #52
|
|
0c32 0119 ld [$19] 3408 ld([vAC+1]) #53 dst += 256
|
|
0c33 8001 adda $01 3409 adda(1) #54
|
|
0c34 c219 st [$19] 3410 st([vAC+1]) #55
|
|
3411
|
|
0c35 0116 ld [$16] 3412 ld([vPC]) #56 Self-repeating SYS call
|
|
0c36 a002 suba $02 3413 suba(2) #57
|
|
0c37 c216 st [$16] 3414 st([vPC]) #58
|
|
0c38 1403 ld $03,y 3415 ld(hi('REENTER'),Y) #59
|
|
0c39 e0cb jmp y,$cb 3416 jmp(Y,'REENTER') #60
|
|
0c3a 00e0 ld $e0 3417 ld(-64/2) #61
|
|
3418
|
|
0c3b 0200 nop 3419 align(64)
|
|
0c3c 0200 nop
|
|
0c3d 0200 nop
|
|
* 5 times
|
|
3420 label('SYS_Sprite6x_v3_64')
|
|
3421
|
|
SYS_Sprite6x_v3_64:
|
|
0c40 1124 ld [$24],x 3422 ld([sysArgs+0],X) #15 Pixel data source address
|
|
0c41 1525 ld [$25],y 3423 ld([sysArgs+1],Y) #16
|
|
0c42 0d00 ld [y,x] 3424 ld([Y,X]) #17 Next pixel or stop
|
|
0c43 f451 bge .sysDpx1 3425 bpl('.sysDpx1') #18
|
|
0c44 de00 st [y,x++] 3426 st([Y,Xpp]) #19 Just X++
|
|
3427
|
|
0c45 8119 adda [$19] 3428 adda([vAC+1]) #20 Adjust dst for convenience
|
|
0c46 c219 st [$19] 3429 st([vAC+1]) #21
|
|
0c47 0118 ld [$18] 3430 ld([vAC]) #22
|
|
0c48 a006 suba $06 3431 suba(6) #23
|
|
0c49 c218 st [$18] 3432 st([vAC]) #24
|
|
0c4a 0124 ld [$24] 3433 ld([sysArgs+0]) #25 Adjust src for convenience
|
|
0c4b 8001 adda $01 3434 adda(1) #26
|
|
0c4c c224 st [$24] 3435 st([sysArgs+0]) #27
|
|
0c4d 0200 nop 3436 nop() #28
|
|
0c4e 1403 ld $03,y 3437 ld(hi('REENTER'),Y) #29 Normal exit (no self-repeat)
|
|
0c4f e0cb jmp y,$cb 3438 jmp(Y,'REENTER') #30
|
|
0c50 00ef ld $ef 3439 ld(-34/2) #31
|
|
3440
|
|
3441 label('.sysDpx1')
|
|
.sysDpx1: 0c51 c22b st [$2b] 3442 st([sysArgs+7]) #20 Gobble 6 pixels into buffer (backwards)
|
|
0c52 0d00 ld [y,x] 3443 ld([Y,X]) #21
|
|
0c53 de00 st [y,x++] 3444 st([Y,Xpp]) #22 Just X++
|
|
0c54 c22a st [$2a] 3445 st([sysArgs+6]) #23
|
|
0c55 0d00 ld [y,x] 3446 ld([Y,X]) #24
|
|
0c56 de00 st [y,x++] 3447 st([Y,Xpp]) #25 Just X++
|
|
0c57 c229 st [$29] 3448 st([sysArgs+5]) #26
|
|
0c58 0d00 ld [y,x] 3449 ld([Y,X]) #27
|
|
0c59 de00 st [y,x++] 3450 st([Y,Xpp]) #28 Just X++
|
|
0c5a c228 st [$28] 3451 st([sysArgs+4]) #29
|
|
0c5b 0d00 ld [y,x] 3452 ld([Y,X]) #30
|
|
0c5c de00 st [y,x++] 3453 st([Y,Xpp]) #31 Just X++
|
|
0c5d c227 st [$27] 3454 st([sysArgs+3]) #32
|
|
0c5e 0d00 ld [y,x] 3455 ld([Y,X]) #33
|
|
0c5f de00 st [y,x++] 3456 st([Y,Xpp]) #34 Just X++
|
|
3457
|
|
0c60 1118 ld [$18],x 3458 ld([vAC],X) #35 Screen memory destination address
|
|
0c61 1519 ld [$19],y 3459 ld([vAC+1],Y) #36
|
|
0c62 de00 st [y,x++] 3460 st([Y,Xpp]) #37 Write 6 pixels
|
|
0c63 0127 ld [$27] 3461 ld([sysArgs+3]) #38
|
|
0c64 de00 st [y,x++] 3462 st([Y,Xpp]) #39
|
|
0c65 0128 ld [$28] 3463 ld([sysArgs+4]) #40
|
|
0c66 de00 st [y,x++] 3464 st([Y,Xpp]) #41
|
|
0c67 0129 ld [$29] 3465 ld([sysArgs+5]) #42
|
|
0c68 de00 st [y,x++] 3466 st([Y,Xpp]) #43
|
|
0c69 012a ld [$2a] 3467 ld([sysArgs+6]) #44
|
|
0c6a de00 st [y,x++] 3468 st([Y,Xpp]) #45
|
|
0c6b 012b ld [$2b] 3469 ld([sysArgs+7]) #46
|
|
0c6c de00 st [y,x++] 3470 st([Y,Xpp]) #47
|
|
3471
|
|
0c6d 0124 ld [$24] 3472 ld([sysArgs+0]) #48 src += 6
|
|
0c6e 8006 adda $06 3473 adda(6) #49
|
|
0c6f c224 st [$24] 3474 st([sysArgs+0]) #50
|
|
0c70 0119 ld [$19] 3475 ld([vAC+1]) #51 dst += 256
|
|
0c71 8001 adda $01 3476 adda(1) #52
|
|
0c72 c219 st [$19] 3477 st([vAC+1]) #53
|
|
3478
|
|
0c73 0116 ld [$16] 3479 ld([vPC]) #54 Self-repeating SYS call
|
|
0c74 a002 suba $02 3480 suba(2) #55
|
|
0c75 c216 st [$16] 3481 st([vPC]) #56
|
|
0c76 1403 ld $03,y 3482 ld(hi('REENTER'),Y) #57
|
|
0c77 e0cb jmp y,$cb 3483 jmp(Y,'REENTER') #58
|
|
0c78 00e1 ld $e1 3484 ld(-62/2) #59
|
|
3485
|
|
0c79 0200 nop 3486 align(64)
|
|
0c7a 0200 nop
|
|
0c7b 0200 nop
|
|
* 7 times
|
|
3487 label('SYS_Sprite6y_v3_64')
|
|
3488
|
|
SYS_Sprite6y_v3_64:
|
|
0c80 1124 ld [$24],x 3489 ld([sysArgs+0],X) #15 Pixel data source address
|
|
0c81 1525 ld [$25],y 3490 ld([sysArgs+1],Y) #16
|
|
0c82 0d00 ld [y,x] 3491 ld([Y,X]) #17 Next pixel or stop
|
|
0c83 f493 bge .sysDpx2 3492 bpl('.sysDpx2') #18
|
|
0c84 de00 st [y,x++] 3493 st([Y,Xpp]) #19 Just X++
|
|
3494
|
|
0c85 60ff xora $ff 3495 xora(255) #20 Adjust dst for convenience
|
|
0c86 8001 adda $01 3496 adda(1) #21
|
|
0c87 8119 adda [$19] 3497 adda([vAC+1]) #22
|
|
0c88 c219 st [$19] 3498 st([vAC+1]) #23
|
|
0c89 0118 ld [$18] 3499 ld([vAC]) #24
|
|
0c8a 8006 adda $06 3500 adda(6) #25
|
|
0c8b c218 st [$18] 3501 st([vAC]) #26
|
|
0c8c 0124 ld [$24] 3502 ld([sysArgs+0]) #27 Adjust src for convenience
|
|
0c8d 8001 adda $01 3503 adda(1) #28
|
|
0c8e c224 st [$24] 3504 st([sysArgs+0]) #29
|
|
0c8f 0200 nop 3505 nop() #30
|
|
0c90 1403 ld $03,y 3506 ld(hi('REENTER'),Y) #31 Normal exit (no self-repeat)
|
|
0c91 e0cb jmp y,$cb 3507 jmp(Y,'REENTER') #32
|
|
0c92 00ee ld $ee 3508 ld(-36/2) #33
|
|
3509
|
|
3510 label('.sysDpx2')
|
|
.sysDpx2: 0c93 c226 st [$26] 3511 st([sysArgs+2]) #20 Gobble 6 pixels into buffer
|
|
0c94 0d00 ld [y,x] 3512 ld([Y,X]) #21
|
|
0c95 de00 st [y,x++] 3513 st([Y,Xpp]) #22 Just X++
|
|
0c96 c227 st [$27] 3514 st([sysArgs+3]) #23
|
|
0c97 0d00 ld [y,x] 3515 ld([Y,X]) #24
|
|
0c98 de00 st [y,x++] 3516 st([Y,Xpp]) #25 Just X++
|
|
0c99 c228 st [$28] 3517 st([sysArgs+4]) #26
|
|
0c9a 0d00 ld [y,x] 3518 ld([Y,X]) #27
|
|
0c9b de00 st [y,x++] 3519 st([Y,Xpp]) #28 Just X++
|
|
0c9c c229 st [$29] 3520 st([sysArgs+5]) #29
|
|
0c9d 0d00 ld [y,x] 3521 ld([Y,X]) #30
|
|
0c9e de00 st [y,x++] 3522 st([Y,Xpp]) #31 Just X++
|
|
0c9f c22a st [$2a] 3523 st([sysArgs+6]) #32
|
|
0ca0 0d00 ld [y,x] 3524 ld([Y,X]) #33
|
|
0ca1 de00 st [y,x++] 3525 st([Y,Xpp]) #34 Just X++
|
|
0ca2 c22b st [$2b] 3526 st([sysArgs+7]) #35
|
|
3527
|
|
0ca3 1118 ld [$18],x 3528 ld([vAC],X) #36 Screen memory destination address
|
|
0ca4 1519 ld [$19],y 3529 ld([vAC+1],Y) #37
|
|
0ca5 0126 ld [$26] 3530 ld([sysArgs+2]) #38 Write 6 pixels
|
|
0ca6 de00 st [y,x++] 3531 st([Y,Xpp]) #39
|
|
0ca7 0127 ld [$27] 3532 ld([sysArgs+3]) #40
|
|
0ca8 de00 st [y,x++] 3533 st([Y,Xpp]) #41
|
|
0ca9 0128 ld [$28] 3534 ld([sysArgs+4]) #42
|
|
0caa de00 st [y,x++] 3535 st([Y,Xpp]) #43
|
|
0cab 0129 ld [$29] 3536 ld([sysArgs+5]) #44
|
|
0cac de00 st [y,x++] 3537 st([Y,Xpp]) #45
|
|
0cad 012a ld [$2a] 3538 ld([sysArgs+6]) #46
|
|
0cae de00 st [y,x++] 3539 st([Y,Xpp]) #47
|
|
0caf 012b ld [$2b] 3540 ld([sysArgs+7]) #48
|
|
0cb0 de00 st [y,x++] 3541 st([Y,Xpp]) #49
|
|
3542
|
|
0cb1 0124 ld [$24] 3543 ld([sysArgs+0]) #50 src += 6
|
|
0cb2 8006 adda $06 3544 adda(6) #51
|
|
0cb3 c224 st [$24] 3545 st([sysArgs+0]) #52
|
|
0cb4 0119 ld [$19] 3546 ld([vAC+1]) #53 dst -= 256
|
|
0cb5 a001 suba $01 3547 suba(1) #54
|
|
0cb6 c219 st [$19] 3548 st([vAC+1]) #55
|
|
3549
|
|
0cb7 0116 ld [$16] 3550 ld([vPC]) #56 Self-repeating SYS call
|
|
0cb8 a002 suba $02 3551 suba(2) #57
|
|
0cb9 c216 st [$16] 3552 st([vPC]) #58
|
|
0cba 1403 ld $03,y 3553 ld(hi('REENTER'),Y) #59
|
|
0cbb e0cb jmp y,$cb 3554 jmp(Y,'REENTER') #60
|
|
0cbc 00e0 ld $e0 3555 ld(-64/2) #61
|
|
3556
|
|
0cbd 0200 nop 3557 align(64)
|
|
0cbe 0200 nop
|
|
0cbf 0200 nop
|
|
3558 label('SYS_Sprite6xy_v3_64')
|
|
3559
|
|
SYS_Sprite6xy_v3_64:
|
|
0cc0 1124 ld [$24],x 3560 ld([sysArgs+0],X) #15 Pixel data source address
|
|
0cc1 1525 ld [$25],y 3561 ld([sysArgs+1],Y) #16
|
|
0cc2 0d00 ld [y,x] 3562 ld([Y,X]) #17 Next pixel or stop
|
|
0cc3 f4d3 bge .sysDpx3 3563 bpl('.sysDpx3') #18
|
|
0cc4 de00 st [y,x++] 3564 st([Y,Xpp]) #19 Just X++
|
|
3565
|
|
0cc5 60ff xora $ff 3566 xora(255) #20 Adjust dst for convenience
|
|
0cc6 8001 adda $01 3567 adda(1) #21
|
|
0cc7 8119 adda [$19] 3568 adda([vAC+1]) #22
|
|
0cc8 c219 st [$19] 3569 st([vAC+1]) #23
|
|
0cc9 0118 ld [$18] 3570 ld([vAC]) #24
|
|
0cca a006 suba $06 3571 suba(6) #25
|
|
0ccb c218 st [$18] 3572 st([vAC]) #26
|
|
0ccc 0124 ld [$24] 3573 ld([sysArgs+0]) #27 Adjust src for convenience
|
|
0ccd 8001 adda $01 3574 adda(1) #28
|
|
0cce c224 st [$24] 3575 st([sysArgs+0]) #29
|
|
0ccf 0200 nop 3576 nop() #30
|
|
0cd0 1403 ld $03,y 3577 ld(hi('REENTER'),Y) #31 Normal exit (no self-repeat)
|
|
0cd1 e0cb jmp y,$cb 3578 jmp(Y,'REENTER') #32
|
|
0cd2 00ee ld $ee 3579 ld(-36/2) #33
|
|
3580
|
|
3581 label('.sysDpx3')
|
|
.sysDpx3: 0cd3 c22b st [$2b] 3582 st([sysArgs+7]) #20 Gobble 6 pixels into buffer (backwards)
|
|
0cd4 0d00 ld [y,x] 3583 ld([Y,X]) #21
|
|
0cd5 de00 st [y,x++] 3584 st([Y,Xpp]) #22 Just X++
|
|
0cd6 c22a st [$2a] 3585 st([sysArgs+6]) #23
|
|
0cd7 0d00 ld [y,x] 3586 ld([Y,X]) #24
|
|
0cd8 de00 st [y,x++] 3587 st([Y,Xpp]) #25 Just X++
|
|
0cd9 c229 st [$29] 3588 st([sysArgs+5]) #26
|
|
0cda 0d00 ld [y,x] 3589 ld([Y,X]) #27
|
|
0cdb de00 st [y,x++] 3590 st([Y,Xpp]) #28 Just X++
|
|
0cdc c228 st [$28] 3591 st([sysArgs+4]) #29
|
|
0cdd 0d00 ld [y,x] 3592 ld([Y,X]) #30
|
|
0cde de00 st [y,x++] 3593 st([Y,Xpp]) #31 Just X++
|
|
0cdf c227 st [$27] 3594 st([sysArgs+3]) #32
|
|
0ce0 0d00 ld [y,x] 3595 ld([Y,X]) #33
|
|
0ce1 de00 st [y,x++] 3596 st([Y,Xpp]) #34 Just X++
|
|
3597
|
|
0ce2 1118 ld [$18],x 3598 ld([vAC],X) #35 Screen memory destination address
|
|
0ce3 1519 ld [$19],y 3599 ld([vAC+1],Y) #36
|
|
0ce4 de00 st [y,x++] 3600 st([Y,Xpp]) #37 Write 6 pixels
|
|
0ce5 0127 ld [$27] 3601 ld([sysArgs+3]) #38
|
|
0ce6 de00 st [y,x++] 3602 st([Y,Xpp]) #39
|
|
0ce7 0128 ld [$28] 3603 ld([sysArgs+4]) #40
|
|
0ce8 de00 st [y,x++] 3604 st([Y,Xpp]) #41
|
|
0ce9 0129 ld [$29] 3605 ld([sysArgs+5]) #42
|
|
0cea de00 st [y,x++] 3606 st([Y,Xpp]) #43
|
|
0ceb 012a ld [$2a] 3607 ld([sysArgs+6]) #44
|
|
0cec de00 st [y,x++] 3608 st([Y,Xpp]) #45
|
|
0ced 012b ld [$2b] 3609 ld([sysArgs+7]) #46
|
|
0cee de00 st [y,x++] 3610 st([Y,Xpp]) #47
|
|
3611
|
|
0cef 0124 ld [$24] 3612 ld([sysArgs+0]) #48 src += 6
|
|
0cf0 8006 adda $06 3613 adda(6) #49
|
|
0cf1 c224 st [$24] 3614 st([sysArgs+0]) #50
|
|
0cf2 0119 ld [$19] 3615 ld([vAC+1]) #51 dst -= 256
|
|
0cf3 a001 suba $01 3616 suba(1) #52
|
|
0cf4 c219 st [$19] 3617 st([vAC+1]) #53
|
|
3618
|
|
0cf5 0116 ld [$16] 3619 ld([vPC]) #54 Self-repeating SYS call
|
|
0cf6 a002 suba $02 3620 suba(2) #55
|
|
0cf7 c216 st [$16] 3621 st([vPC]) #56
|
|
0cf8 1403 ld $03,y 3622 ld(hi('REENTER'),Y) #57
|
|
0cf9 e0cb jmp y,$cb 3623 jmp(Y,'REENTER') #58
|
|
0cfa 00e1 ld $e1 3624 ld(-62/2) #59
|
|
3625
|
|
3626 #-----------------------------------------------------------------------
|
|
3627
|
|
3628 label('sys_ExpanderControl')
|
|
3629
|
|
sys_ExpanderControl:
|
|
0cfb 2118 anda [$18] 3630 anda([vAC]) #18
|
|
0cfc d218 st [$18],x 3631 st([vAC],X) #19
|
|
0cfd 1401 ld $01,y 3632 ld(hi(ctrlBits),Y) #20
|
|
0cfe caf8 st [y,$f8] 3633 st([Y,ctrlBits]) #21 Set control variable
|
|
0cff 1519 ld [$19],y 3634 ld([vAC+1],Y) #22 MOSI (A15)
|
|
0d00 cd00 ctrl y,x 3635 ctrl(Y,X) #23 Try set the expander control register
|
|
3636
|
|
0d01 0127 ld [$27] 3637 ld([sysArgs+3]) #24 Prepare for SYS_SpiExchangeBytes
|
|
3638 assert pc()&255 < 255-3 # Beware of page crossing: asm.py won't warn
|
|
0d02 ec05 bne $0d05 3639 bne(pc()+3) #25
|
|
0d03 fc05 bra $0d05 3640 bra(pc()+2) #26
|
|
0d04 0125 ld [$25] 3641 ld([sysArgs+1]) #27
|
|
0d05 c227 st [$27] 3642 st([sysArgs+3]) #27,28 (must be idempotent)
|
|
3643
|
|
0d06 1403 ld $03,y 3644 ld(hi('REENTER'),Y) #29
|
|
0d07 e0cb jmp y,$cb 3645 jmp(Y,'REENTER') #30
|
|
0d08 00ef ld $ef 3646 ld(-34/2) #31
|
|
3647
|
|
3648 #-----------------------------------------------------------------------
|
|
3649
|
|
3650 label('sys_SpiExchangeBytes')
|
|
3651
|
|
sys_SpiExchangeBytes:
|
|
0d09 09f8 ld [y,$f8] 3652 ld([Y,ctrlBits]) #18
|
|
0d0a c228 st [$28] 3653 st([sysArgs+4]) #19
|
|
3654
|
|
0d0b 1124 ld [$24],x 3655 ld([sysArgs+0],X) #20 Fetch byte to send
|
|
0d0c 1525 ld [$25],y 3656 ld([sysArgs+1],Y) #21
|
|
0d0d 0d00 ld [y,x] 3657 ld([Y,X]) #22
|
|
3658
|
|
3659 for i in range(8):
|
|
3660 st([vTmp],Y);C('Bit %d'%(7-i))#23+i*12
|
|
0d0e d61d st [$1d],y ;Bit 7
|
|
0d0f 1128 ld [$28],x 3661 ld([sysArgs+4],X) #24+i*12
|
|
0d10 dd00 ctrl y,x++ 3662 ctrl(Y,Xpp) #25+i*12 Set MOSI
|
|
0d11 dd00 ctrl y,x++ 3663 ctrl(Y,Xpp) #26+i*12 Raise SCLK, disable RAM!
|
|
0d12 0100 ld [$00] 3664 ld([0]) #27+i*12 Get MISO
|
|
0d13 200f anda $0f 3665 anda(0b00001111) #28+i*12 This is why R1 as pull-DOWN is simpler
|
|
0d14 f017 beq $0d17 3666 beq(pc()+3) #29+i*12
|
|
0d15 fc17 bra $0d17 3667 bra(pc()+2) #30+i*12
|
|
0d16 0001 ld $01 3668 ld(1) #31+i*12
|
|
0d17 cd00 ctrl y,x 3669 ctrl(Y,X) #32+i*12,29+i*12 (Must be idempotent) Lower SCLK
|
|
0d18 811d adda [$1d] 3670 adda([vTmp]) #33+i*12 Shift
|
|
0d19 811d adda [$1d] 3671 adda([vTmp]) #34+i*12
|
|
0d1a d61d st [$1d],y ;Bit 6
|
|
0d1b 1128 ld [$28],x
|
|
0d1c dd00 ctrl y,x++
|
|
0d1d dd00 ctrl y,x++
|
|
0d1e 0100 ld [$00]
|
|
0d1f 200f anda $0f
|
|
0d20 f023 beq $0d23
|
|
0d21 fc23 bra $0d23
|
|
0d22 0001 ld $01
|
|
0d23 cd00 ctrl y,x
|
|
0d24 811d adda [$1d]
|
|
0d25 811d adda [$1d]
|
|
0d26 d61d st [$1d],y ;Bit 5
|
|
0d27 1128 ld [$28],x
|
|
0d28 dd00 ctrl y,x++
|
|
0d29 dd00 ctrl y,x++
|
|
0d2a 0100 ld [$00]
|
|
0d2b 200f anda $0f
|
|
0d2c f02f beq $0d2f
|
|
0d2d fc2f bra $0d2f
|
|
0d2e 0001 ld $01
|
|
0d2f cd00 ctrl y,x
|
|
0d30 811d adda [$1d]
|
|
0d31 811d adda [$1d]
|
|
0d32 d61d st [$1d],y ;Bit 4
|
|
0d33 1128 ld [$28],x
|
|
0d34 dd00 ctrl y,x++
|
|
0d35 dd00 ctrl y,x++
|
|
0d36 0100 ld [$00]
|
|
0d37 200f anda $0f
|
|
0d38 f03b beq $0d3b
|
|
0d39 fc3b bra $0d3b
|
|
0d3a 0001 ld $01
|
|
0d3b cd00 ctrl y,x
|
|
0d3c 811d adda [$1d]
|
|
0d3d 811d adda [$1d]
|
|
0d3e d61d st [$1d],y ;Bit 3
|
|
0d3f 1128 ld [$28],x
|
|
0d40 dd00 ctrl y,x++
|
|
0d41 dd00 ctrl y,x++
|
|
0d42 0100 ld [$00]
|
|
0d43 200f anda $0f
|
|
0d44 f047 beq $0d47
|
|
0d45 fc47 bra $0d47
|
|
0d46 0001 ld $01
|
|
0d47 cd00 ctrl y,x
|
|
0d48 811d adda [$1d]
|
|
0d49 811d adda [$1d]
|
|
0d4a d61d st [$1d],y ;Bit 2
|
|
0d4b 1128 ld [$28],x
|
|
0d4c dd00 ctrl y,x++
|
|
0d4d dd00 ctrl y,x++
|
|
0d4e 0100 ld [$00]
|
|
0d4f 200f anda $0f
|
|
0d50 f053 beq $0d53
|
|
0d51 fc53 bra $0d53
|
|
0d52 0001 ld $01
|
|
0d53 cd00 ctrl y,x
|
|
0d54 811d adda [$1d]
|
|
0d55 811d adda [$1d]
|
|
0d56 d61d st [$1d],y ;Bit 1
|
|
0d57 1128 ld [$28],x
|
|
0d58 dd00 ctrl y,x++
|
|
0d59 dd00 ctrl y,x++
|
|
0d5a 0100 ld [$00]
|
|
0d5b 200f anda $0f
|
|
0d5c f05f beq $0d5f
|
|
0d5d fc5f bra $0d5f
|
|
0d5e 0001 ld $01
|
|
0d5f cd00 ctrl y,x
|
|
0d60 811d adda [$1d]
|
|
0d61 811d adda [$1d]
|
|
0d62 d61d st [$1d],y ;Bit 0
|
|
0d63 1128 ld [$28],x
|
|
0d64 dd00 ctrl y,x++
|
|
0d65 dd00 ctrl y,x++
|
|
0d66 0100 ld [$00]
|
|
0d67 200f anda $0f
|
|
0d68 f06b beq $0d6b
|
|
0d69 fc6b bra $0d6b
|
|
0d6a 0001 ld $01
|
|
0d6b cd00 ctrl y,x
|
|
0d6c 811d adda [$1d]
|
|
0d6d 811d adda [$1d]
|
|
3672
|
|
0d6e 1124 ld [$24],x 3673 ld([sysArgs+0],X) #119 Store received byte
|
|
0d6f 1527 ld [$27],y 3674 ld([sysArgs+3],Y) #120
|
|
0d70 ce00 st [y,x] 3675 st([Y,X]) #121
|
|
3676
|
|
0d71 0124 ld [$24] 3677 ld([sysArgs+0]) #122 Advance pointer
|
|
0d72 8001 adda $01 3678 adda(1) #123
|
|
0d73 c224 st [$24] 3679 st([sysArgs+0]) #124
|
|
3680
|
|
0d74 6126 xora [$26] 3681 xora([sysArgs+2]) #125 Reached end?
|
|
0d75 f07c beq .sysSpi#128 3682 beq('.sysSpi#128') #126
|
|
3683
|
|
0d76 0116 ld [$16] 3684 ld([vPC]) #127 Self-repeating SYS call
|
|
0d77 a002 suba $02 3685 suba(2) #128
|
|
0d78 c216 st [$16] 3686 st([vPC]) #129
|
|
0d79 1403 ld $03,y 3687 ld(hi('NEXTY'),Y) #130
|
|
0d7a e000 jmp y,$00 3688 jmp(Y,'NEXTY') #131
|
|
0d7b 00bd ld $bd 3689 ld(-134/2) #132
|
|
3690
|
|
3691 label('.sysSpi#128')
|
|
.sysSpi#128: 0d7c 1403 ld $03,y 3692 ld(hi('NEXTY'),Y) #128 Continue program
|
|
0d7d e000 jmp y,$00 3693 jmp(Y,'NEXTY') #129
|
|
0d7e 00be ld $be 3694 ld(-132/2) #130
|
|
3695
|
|
3696 #-----------------------------------------------------------------------
|
|
3697
|
|
3698 label('sys_v6502')
|
|
3699
|
|
sys_v6502: 0d7f d605 st [$05],y 3700 st([vCpuSelect],Y) #18 Activate v6502
|
|
0d80 00f5 ld $f5 3701 ld(-22/2) #19
|
|
0d81 e0ff jmp y,$ff 3702 jmp(Y,'v6502_ENTER') #20 Transfer control in the same time slice
|
|
0d82 8115 adda [$15] 3703 adda([vTicks]) #21
|
|
3704 assert (38 - 22)//2 >= v6502_adjust
|
|
3705
|
|
3706 #-----------------------------------------------------------------------
|
|
3707 # MOS 6502 emulator
|
|
3708 #-----------------------------------------------------------------------
|
|
3709
|
|
3710 # Some quirks:
|
|
3711 # - Stack in zero page instead of page 1
|
|
3712 # - No interrupts
|
|
3713 # - No decimal mode (may never be added). D flag is emulated but ignored.
|
|
3714 # - BRK switches back to running 16-bits vCPU
|
|
3715 # - Illegal opcodes map to BRK, but can read ghost operands before trapping
|
|
3716 # - Illegal opcode $ff won't be trapped and cause havoc instead
|
|
3717
|
|
3718 # Big things TODO:
|
|
3719 # XXX Tuning, put most frequent instructions in the primary page
|
|
3720
|
|
3721 label('v6502_ror')
|
|
3722 assert v6502_Cflag == 1
|
|
v6502_ror: 0d83 1525 ld [$25],y 3723 ld([v6502_ADH],Y) #12
|
|
0d84 00fc ld $fc 3724 ld(-46//2+v6502_maxTicks) #13 Is there enough time for the excess ticks?
|
|
0d85 8115 adda [$15] 3725 adda([vTicks]) #14
|
|
0d86 e89a blt .recheck17 3726 blt('.recheck17') #15
|
|
0d87 0127 ld [$27] 3727 ld([v6502_P]) #16 Transfer C to "bit 8"
|
|
0d88 2001 anda $01 3728 anda(1) #17
|
|
0d89 807f adda $7f 3729 adda(127) #18
|
|
0d8a 2080 anda $80 3730 anda(128) #19
|
|
0d8b c219 st [$19] 3731 st([v6502_BI]) #20 The real 6502 wouldn't use BI for this
|
|
0d8c 0127 ld [$27] 3732 ld([v6502_P]) #21 Transfer bit 0 to C
|
|
0d8d 20fe anda $fe 3733 anda(~1) #22
|
|
0d8e c227 st [$27] 3734 st([v6502_P]) #23
|
|
0d8f 0d00 ld [y,x] 3735 ld([Y,X]) #24
|
|
0d90 2001 anda $01 3736 anda(1) #25
|
|
0d91 4127 ora [$27] 3737 ora([v6502_P]) #26
|
|
0d92 c227 st [$27] 3738 st([v6502_P]) #27
|
|
0d93 00ee ld $ee 3739 ld('v6502_ror#38') #28 Shift table lookup
|
|
0d94 c21d st [$1d] 3740 st([vTmp]) #29
|
|
0d95 0d00 ld [y,x] 3741 ld([Y,X]) #30
|
|
0d96 20fe anda $fe 3742 anda(~1) #31
|
|
0d97 1405 ld $05,y 3743 ld(hi('shiftTable'),Y) #32
|
|
0d98 e200 jmp y,ac 3744 jmp(Y,AC) #33
|
|
0d99 fcff bra $ff 3745 bra(255) #34 bra shiftTable+255
|
|
3746 label('.recheck17')
|
|
.recheck17: 0d9a 140e ld $0e,y 3747 ld(hi('v6502_check'),Y) #17 Go back to time check before dispatch
|
|
0d9b e0f2 jmp y,$f2 3748 jmp(Y,'v6502_check') #18
|
|
0d9c 00f6 ld $f6 3749 ld(-20/2) #19
|
|
3750
|
|
3751 label('v6502_lsr')
|
|
3752 assert v6502_Cflag == 1
|
|
v6502_lsr: 0d9d 1525 ld [$25],y 3753 ld([v6502_ADH],Y) #12
|
|
0d9e 0127 ld [$27] 3754 ld([v6502_P]) #13 Transfer bit 0 to C
|
|
0d9f 20fe anda $fe 3755 anda(~1) #14
|
|
0da0 c227 st [$27] 3756 st([v6502_P]) #15
|
|
0da1 0d00 ld [y,x] 3757 ld([Y,X]) #16
|
|
0da2 2001 anda $01 3758 anda(1) #17
|
|
0da3 4127 ora [$27] 3759 ora([v6502_P]) #18
|
|
0da4 c227 st [$27] 3760 st([v6502_P]) #19
|
|
0da5 00e7 ld $e7 3761 ld('v6502_lsr#30') #20 Shift table lookup
|
|
0da6 c21d st [$1d] 3762 st([vTmp]) #21
|
|
0da7 0d00 ld [y,x] 3763 ld([Y,X]) #22
|
|
0da8 20fe anda $fe 3764 anda(~1) #23
|
|
0da9 1405 ld $05,y 3765 ld(hi('shiftTable'),Y) #24
|
|
0daa e200 jmp y,ac 3766 jmp(Y,AC) #25
|
|
0dab fcff bra $ff 3767 bra(255) #26 bra shiftTable+255
|
|
3768
|
|
3769 label('v6502_rol')
|
|
3770 assert v6502_Cflag == 1
|
|
v6502_rol: 0dac 1525 ld [$25],y 3771 ld([v6502_ADH],Y) #12
|
|
0dad 0d00 ld [y,x] 3772 ld([Y,X]) #13
|
|
0dae 2080 anda $80 3773 anda(0x80) #14
|
|
0daf c21d st [$1d] 3774 st([v6502_Tmp]) #15
|
|
0db0 0127 ld [$27] 3775 ld([v6502_P]) #16
|
|
0db1 2001 anda $01 3776 anda(1) #17
|
|
3777 label('.rol#18')
|
|
.rol#18: 0db2 8d00 adda [y,x] 3778 adda([Y,X]) #18
|
|
0db3 8d00 adda [y,x] 3779 adda([Y,X]) #19
|
|
0db4 ce00 st [y,x] 3780 st([Y,X]) #20
|
|
0db5 c228 st [$28] 3781 st([v6502_Qz]) #21 Z flag
|
|
0db6 c229 st [$29] 3782 st([v6502_Qn]) #22 N flag
|
|
0db7 0127 ld [$27] 3783 ld([v6502_P]) #23 C Flag
|
|
0db8 20fe anda $fe 3784 anda(~1) #24
|
|
0db9 111d ld [$1d],x 3785 ld([v6502_Tmp],X) #25
|
|
0dba 4500 ora [x] 3786 ora([X]) #26
|
|
0dbb c227 st [$27] 3787 st([v6502_P]) #27
|
|
0dbc 140e ld $0e,y 3788 ld(hi('v6502_next'),Y) #28
|
|
0dbd 00f0 ld $f0 3789 ld(-32/2) #29
|
|
0dbe e020 jmp y,$20 3790 jmp(Y,'v6502_next') #30
|
|
3791 #nop() #31 Overlap
|
|
3792 #
|
|
3793 label('v6502_asl')
|
|
v6502_asl: 0dbf 1525 ld [$25],y 3794 ld([v6502_ADH],Y) #12,32
|
|
0dc0 0d00 ld [y,x] 3795 ld([Y,X]) #13
|
|
0dc1 2080 anda $80 3796 anda(0x80) #14
|
|
0dc2 c21d st [$1d] 3797 st([v6502_Tmp]) #15
|
|
0dc3 fcb2 bra .rol#18 3798 bra('.rol#18') #16
|
|
0dc4 0000 ld $00 3799 ld(0) #17
|
|
3800
|
|
3801 label('v6502_jmp1')
|
|
v6502_jmp1: 0dc5 0200 nop 3802 nop() #12
|
|
0dc6 0124 ld [$24] 3803 ld([v6502_ADL]) #13
|
|
0dc7 c21a st [$1a] 3804 st([v6502_PCL]) #14
|
|
0dc8 0125 ld [$25] 3805 ld([v6502_ADH]) #15
|
|
0dc9 c21b st [$1b] 3806 st([v6502_PCH]) #16
|
|
0dca 140e ld $0e,y 3807 ld(hi('v6502_next'),Y) #17
|
|
0dcb e020 jmp y,$20 3808 jmp(Y,'v6502_next') #18
|
|
0dcc 00f6 ld $f6 3809 ld(-20/2) #19
|
|
3810
|
|
3811 label('v6502_jmp2')
|
|
v6502_jmp2: 0dcd 0200 nop 3812 nop() #12
|
|
0dce 1525 ld [$25],y 3813 ld([v6502_ADH],Y) #13
|
|
0dcf 0d00 ld [y,x] 3814 ld([Y,X]) #14
|
|
0dd0 de00 st [y,x++] 3815 st([Y,Xpp]) #15 (Just X++) Wrap around: bug compatible with NMOS
|
|
0dd1 c21a st [$1a] 3816 st([v6502_PCL]) #16
|
|
0dd2 0d00 ld [y,x] 3817 ld([Y,X]) #17
|
|
0dd3 c21b st [$1b] 3818 st([v6502_PCH]) #18
|
|
0dd4 140e ld $0e,y 3819 ld(hi('v6502_next'),Y) #19
|
|
0dd5 e020 jmp y,$20 3820 jmp(Y,'v6502_next') #20
|
|
0dd6 00f5 ld $f5 3821 ld(-22/2) #21
|
|
3822
|
|
3823 label('v6502_pla')
|
|
v6502_pla: 0dd7 011c ld [$1c] 3824 ld([v6502_S]) #12
|
|
0dd8 1200 ld ac,x 3825 ld(AC,X) #13
|
|
0dd9 8001 adda $01 3826 adda(1) #14
|
|
0dda c21c st [$1c] 3827 st([v6502_S]) #15
|
|
0ddb 0500 ld [x] 3828 ld([X]) #16
|
|
0ddc c218 st [$18] 3829 st([v6502_A]) #17
|
|
0ddd c228 st [$28] 3830 st([v6502_Qz]) #18 Z flag
|
|
0dde c229 st [$29] 3831 st([v6502_Qn]) #19 N flag
|
|
0ddf 140e ld $0e,y 3832 ld(hi('v6502_next'),Y) #20
|
|
0de0 00f4 ld $f4 3833 ld(-24/2) #21
|
|
0de1 e020 jmp y,$20 3834 jmp(Y,'v6502_next') #22
|
|
3835 #nop() #23 Overlap
|
|
3836 #
|
|
3837 label('v6502_pha')
|
|
v6502_pha: 0de2 140e ld $0e,y 3838 ld(hi('v6502_next'),Y) #12,24
|
|
0de3 011c ld [$1c] 3839 ld([v6502_S]) #13
|
|
0de4 a001 suba $01 3840 suba(1) #14
|
|
0de5 d21c st [$1c],x 3841 st([v6502_S],X) #15
|
|
0de6 0118 ld [$18] 3842 ld([v6502_A]) #16
|
|
0de7 c600 st [x] 3843 st([X]) #17
|
|
0de8 e020 jmp y,$20 3844 jmp(Y,'v6502_next') #18
|
|
0de9 00f6 ld $f6 3845 ld(-20/2) #19
|
|
3846
|
|
3847 label('v6502_brk')
|
|
v6502_brk: 0dea 0002 ld $02 3848 ld(hi('ENTER')) #12 Switch to vCPU
|
|
0deb c205 st [$05] 3849 st([vCpuSelect]) #13
|
|
3850 assert v6502_A == vAC
|
|
0dec 0000 ld $00 3851 ld(0) #14
|
|
0ded c219 st [$19] 3852 st([vAC+1]) #15
|
|
0dee 1403 ld $03,y 3853 ld(hi('REENTER'),Y) #16 Switch in the current time slice
|
|
0def 00fb ld $fb 3854 ld(-22//2+v6502_adjust) #17
|
|
0df0 e0cb jmp y,$cb 3855 jmp(Y,'REENTER') #18
|
|
0df1 0200 nop 3856 nop() #19
|
|
3857
|
|
3858 # All interpreter entry points must share the same page offset, because
|
|
3859 # this offset is hard-coded as immediate operand in the video driver.
|
|
3860 # The Gigatron's original vCPU's 'ENTER' label is already at $2ff, so we
|
|
3861 # just use $dff for 'v6502_ENTER'. v6502 actually has two entry points.
|
|
3862 # The other is 'v6502_RESUME' at $10ff. It is used for instructions
|
|
3863 # that were fetched but not yet executed. Allowing the split gives finer
|
|
3864 # granulariy, and hopefully more throughput for the simpler instructions.
|
|
3865 # (There is no "overhead" for allowing instruction splitting, because
|
|
3866 # both emulation phases must administer [vTicks] anyway.)
|
|
3867 while pc()&255 < 255:
|
|
0df2 0200 nop 3868 nop()
|
|
0df3 0200 nop
|
|
0df4 0200 nop
|
|
* 13 times
|
|
3869 label('v6502_ENTER')
|
|
v6502_ENTER: 0dff fc22 bra v6502_next2 3870 bra('v6502_next2') #0 v6502 primary entry point
|
|
3871 # --- Page boundary ---
|
|
0e00 a006 suba $06 3872 suba(v6502_adjust) #1,19 Adjust for vCPU/v6520 timing differences
|
|
3873
|
|
3874 #19 Addressing modes
|
|
3875 ( 'v6502_mode0' ); bra('v6502_modeIZX'); bra('v6502_modeIMM'); bra('v6502_modeILL') # $00 xxx000xx
|
|
0e01 fce0 bra v6502_modeIZX
|
|
0e02 fc42 bra v6502_modeIMM
|
|
0e03 fc58 bra v6502_modeIMP
|
|
3876 bra('v6502_modeZP'); bra('v6502_modeZP'); bra('v6502_modeZP'); bra('v6502_modeILL') # $04 xxx001xx
|
|
0e04 fc5d bra v6502_modeZP
|
|
0e05 fc5d bra v6502_modeZP
|
|
0e06 fc5d bra v6502_modeZP
|
|
0e07 fc58 bra v6502_modeIMP
|
|
3877 bra('v6502_modeIMP'); bra('v6502_modeIMM'); bra('v6502_modeACC'); bra('v6502_modeILL') # $08 xxx010xx
|
|
0e08 fc58 bra v6502_modeIMP
|
|
0e09 fc42 bra v6502_modeIMM
|
|
0e0a fc52 bra v6502_modeACC
|
|
0e0b fc58 bra v6502_modeIMP
|
|
3878 bra('v6502_modeABS'); bra('v6502_modeABS'); bra('v6502_modeABS'); bra('v6502_modeILL') # $0c xxx011xx
|
|
0e0c fc78 bra v6502_modeABS
|
|
0e0d fc78 bra v6502_modeABS
|
|
0e0e fc78 bra v6502_modeABS
|
|
0e0f fc58 bra v6502_modeIMP
|
|
3879 bra('v6502_modeREL'); bra('v6502_modeIZY'); bra('v6502_modeIMM'); bra('v6502_modeILL') # $10 xxx100xx
|
|
0e10 fccf bra v6502_modeREL
|
|
0e11 fcab bra v6502_modeIZY
|
|
0e12 fc42 bra v6502_modeIMM
|
|
0e13 fc58 bra v6502_modeIMP
|
|
3880 bra('v6502_modeZPX'); bra('v6502_modeZPX'); bra('v6502_modeZPX'); bra('v6502_modeILL') # $14 xxx101xx
|
|
0e14 fc5b bra v6502_modeZPX
|
|
0e15 fc5b bra v6502_modeZPX
|
|
0e16 fc5b bra v6502_modeZPX
|
|
0e17 fc58 bra v6502_modeIMP
|
|
3881 bra('v6502_modeIMP'); bra('v6502_modeABY'); bra('v6502_modeIMP'); bra('v6502_modeILL') # $18 xxx110xx
|
|
0e18 fc58 bra v6502_modeIMP
|
|
0e19 fc7b bra v6502_modeABY
|
|
0e1a fc58 bra v6502_modeIMP
|
|
0e1b fc58 bra v6502_modeIMP
|
|
3882 bra('v6502_modeABX'); bra('v6502_modeABX'); bra('v6502_modeABX'); bra('v6502_modeILL') # $1c xxx111xx
|
|
0e1c fc7a bra v6502_modeABX
|
|
0e1d fc7a bra v6502_modeABX
|
|
0e1e fc7a bra v6502_modeABX
|
|
0e1f fc58 bra v6502_modeIMP
|
|
3883
|
|
3884 # Special encoding cases for emulator:
|
|
3885 # $00 BRK - but gets mapped to #$DD handled in v6502_mode0
|
|
3886 # $20 JSR $DDDD but gets mapped to #$DD handled in v6502_mode0 and v6502_JSR
|
|
3887 # $40 RTI - but gets mapped to #$DD handled in v6502_mode0
|
|
3888 # $60 RTS - but gets mapped to #$DD handled in v6502_mode0
|
|
3889 # $6C JMP ($DDDD) but gets mapped to $DDDD handled in v6502_JMP2
|
|
3890 # $96 STX $DD,Y but gets mapped to $DD,X handled in v6502_STX2
|
|
3891 # $B6 LDX $DD,Y but gets mapped to $DD,X handled in v6502_LDX2
|
|
3892 # $BE LDX $DDDD,Y but gets mapped to $DDDD,X handled in v6502_modeABX
|
|
3893
|
|
3894 label('v6502_next')
|
|
v6502_next: 0e20 8115 adda [$15] 3895 adda([vTicks]) #0
|
|
3896 blt('v6502_exitBefore') #1 No more ticks
|
|
0e21 e83a blt v6502_exitBefore
|
|
3897 label('v6502_next2')
|
|
v6502_next2: 0e22 c215 st [$15] 3898 st([vTicks]) #2
|
|
3899 #
|
|
3900 # Fetch opcode
|
|
0e23 111a ld [$1a],x 3901 ld([v6502_PCL],X) #3
|
|
0e24 151b ld [$1b],y 3902 ld([v6502_PCH],Y) #4
|
|
0e25 0d00 ld [y,x] 3903 ld([Y,X]) #5 Fetch IR
|
|
0e26 c226 st [$26] 3904 st([v6502_IR]) #6
|
|
0e27 011a ld [$1a] 3905 ld([v6502_PCL]) #7 PC++
|
|
0e28 8001 adda $01 3906 adda(1) #8
|
|
0e29 d21a st [$1a],x 3907 st([v6502_PCL],X) #9
|
|
0e2a f02d beq $0e2d 3908 beq(pc()+3) #10
|
|
0e2b fc2e bra $0e2e 3909 bra(pc()+3) #11
|
|
0e2c 0000 ld $00 3910 ld(0) #12
|
|
0e2d 0001 ld $01 3911 ld(1) #12(!)
|
|
0e2e 811b adda [$1b] 3912 adda([v6502_PCH]) #13
|
|
0e2f d61b st [$1b],y 3913 st([v6502_PCH],Y) #14
|
|
3914 #
|
|
3915 # Get addressing mode and fetch operands
|
|
0e30 0126 ld [$26] 3916 ld([v6502_IR]) #15 Get addressing mode
|
|
0e31 201f anda $1f 3917 anda(31) #16
|
|
0e32 fe00 bra ac 3918 bra(AC) #17
|
|
0e33 fc34 bra .next20 3919 bra('.next20') #18
|
|
3920 # (jump table) #19
|
|
3921 label('.next20')
|
|
.next20: 0e34 0d00 ld [y,x] 3922 ld([Y,X]) #20 Fetch L
|
|
3923 # Most opcodes branch away at this point, but IR & 31 == 0 falls through
|
|
3924 #
|
|
3925 # Implicit Mode for BRK JSR RTI RTS (< 0x80) -- 26 cycles
|
|
3926 # Immediate Mode for LDY CPY CPX (>= 0x80) -- 36 cycles
|
|
3927 label('v6502_mode0')
|
|
v6502_mode0: 0e35 0126 ld [$26] 3928 ld([v6502_IR]) #21 'xxx0000'
|
|
0e36 e845 blt .imm24 3929 bmi('.imm24') #22
|
|
0e37 011b ld [$1b] 3930 ld([v6502_PCH]) #23
|
|
0e38 fcf2 bra v6502_check 3931 bra('v6502_check') #24
|
|
0e39 00f3 ld $f3 3932 ld(-26/2) #25
|
|
3933
|
|
3934 # Resync with video driver. At this point we're returning BEFORE
|
|
3935 # fetching and executing the next instruction.
|
|
3936 label('v6502_exitBefore')
|
|
v6502_exitBefore:
|
|
0e3a 8013 adda $13 3937 adda(v6502_maxTicks) #3 Exit BEFORE fetch
|
|
0e3b e43b bgt $0e3b 3938 bgt(pc()&255) #4 Resync
|
|
0e3c a001 suba $01 3939 suba(1) #5
|
|
0e3d 000d ld $0d 3940 ld(hi('v6502_ENTER')) #6 Set entry point to before 'fetch'
|
|
0e3e c205 st [$05] 3941 st([vCpuSelect]) #7
|
|
0e3f 1401 ld $01,y 3942 ld(hi('vBlankStart'),Y) #8
|
|
0e40 e11e jmp y,[$1e] 3943 jmp(Y,[vReturn]) #9 To video driver
|
|
0e41 0000 ld $00 3944 ld(0) #10
|
|
3945 assert v6502_overhead == 11
|
|
3946
|
|
3947 # Immediate Mode: #$FF -- 36 cycles
|
|
3948 label('v6502_modeIMM')
|
|
v6502_modeIMM:
|
|
0e42 0200 nop 3949 nop() #21 Wait for v6502_mode0 to join
|
|
0e43 0200 nop 3950 nop() #22
|
|
0e44 011b ld [$1b] 3951 ld([v6502_PCH]) #23 Copy PC
|
|
3952 label('.imm24')
|
|
.imm24: 0e45 c225 st [$25] 3953 st([v6502_ADH]) #24
|
|
0e46 011a ld [$1a] 3954 ld([v6502_PCL]) #25
|
|
0e47 d224 st [$24],x 3955 st([v6502_ADL],X) #26
|
|
0e48 8001 adda $01 3956 adda(1) #27 PC++
|
|
0e49 c21a st [$1a] 3957 st([v6502_PCL]) #28
|
|
0e4a f04d beq $0e4d 3958 beq(pc()+3) #29
|
|
0e4b fc4e bra $0e4e 3959 bra(pc()+3) #30
|
|
0e4c 0000 ld $00 3960 ld(0) #31
|
|
0e4d 0001 ld $01 3961 ld(1) #31(!)
|
|
0e4e 811b adda [$1b] 3962 adda([v6502_PCH]) #32
|
|
0e4f c21b st [$1b] 3963 st([v6502_PCH]) #33
|
|
0e50 fcf2 bra v6502_check 3964 bra('v6502_check') #34
|
|
0e51 00ee ld $ee 3965 ld(-36/2) #35
|
|
3966
|
|
3967 # Accumulator Mode: ROL ROR LSL ASR -- 28 cycles
|
|
3968 label('v6502_modeACC')
|
|
v6502_modeACC:
|
|
0e52 0018 ld $18 3969 ld(v6502_A&255) #21 Address of AC
|
|
0e53 d224 st [$24],x 3970 st([v6502_ADL],X) #22
|
|
0e54 0000 ld $00 3971 ld(v6502_A>>8) #23
|
|
0e55 c225 st [$25] 3972 st([v6502_ADH]) #24
|
|
0e56 00f2 ld $f2 3973 ld(-28/2) #25
|
|
0e57 fcf2 bra v6502_check 3974 bra('v6502_check') #26
|
|
3975 #nop() #27 Overlap
|
|
3976 #
|
|
3977 # Implied Mode: no operand -- 24 cycles
|
|
3978 label('v6502_modeILL')
|
|
3979 label('v6502_modeIMP')
|
|
v6502_modeILL:
|
|
v6502_modeIMP:
|
|
0e58 0200 nop 3980 nop() #21,27
|
|
0e59 fcf2 bra v6502_check 3981 bra('v6502_check') #22
|
|
0e5a 00f4 ld $f4 3982 ld(-24/2) #23
|
|
3983
|
|
3984 # Zero Page Modes: $DD $DD,X $DD,Y -- 36 cycles
|
|
3985 label('v6502_modeZPX')
|
|
v6502_modeZPX:
|
|
0e5b fc5f bra .zp23 3986 bra('.zp23') #21
|
|
0e5c 812a adda [$2a] 3987 adda([v6502_X]) #22
|
|
3988 label('v6502_modeZP')
|
|
v6502_modeZP: 0e5d fc5f bra .zp23 3989 bra('.zp23') #21
|
|
0e5e 0200 nop 3990 nop() #22
|
|
3991 label('.zp23')
|
|
.zp23: 0e5f d224 st [$24],x 3992 st([v6502_ADL],X) #23
|
|
0e60 0000 ld $00 3993 ld(0) #24 H=0
|
|
0e61 c225 st [$25] 3994 st([v6502_ADH]) #25
|
|
0e62 0001 ld $01 3995 ld(1) #26 PC++
|
|
0e63 811a adda [$1a] 3996 adda([v6502_PCL]) #27
|
|
0e64 c21a st [$1a] 3997 st([v6502_PCL]) #28
|
|
0e65 f068 beq $0e68 3998 beq(pc()+3) #29
|
|
0e66 fc69 bra $0e69 3999 bra(pc()+3) #30
|
|
0e67 0000 ld $00 4000 ld(0) #31
|
|
0e68 0001 ld $01 4001 ld(1) #31(!)
|
|
0e69 811b adda [$1b] 4002 adda([v6502_PCH]) #32
|
|
0e6a c21b st [$1b] 4003 st([v6502_PCH]) #33
|
|
0e6b fcf2 bra v6502_check 4004 bra('v6502_check') #34
|
|
0e6c 00ee ld $ee 4005 ld(-36/2) #35
|
|
4006
|
|
4007 # Possible retry loop for modeABS and modeIZY. Because these need
|
|
4008 # more time than the v6502_maxTicks of 38 Gigatron cycles, we may
|
|
4009 # have to restart them after the next horizontal pulse.
|
|
4010 label('.retry28')
|
|
.retry28: 0e6d f070 beq $0e70 4011 beq(pc()+3) #28,37 PC--
|
|
0e6e fc71 bra $0e71 4012 bra(pc()+3) #29
|
|
0e6f 0000 ld $00 4013 ld(0) #30
|
|
0e70 00ff ld $ff 4014 ld(-1) #30(!)
|
|
0e71 811b adda [$1b] 4015 adda([v6502_PCH]) #31
|
|
0e72 c21b st [$1b] 4016 st([v6502_PCH]) #32
|
|
0e73 011a ld [$1a] 4017 ld([v6502_PCL]) #33
|
|
0e74 a001 suba $01 4018 suba(1) #34
|
|
0e75 c21a st [$1a] 4019 st([v6502_PCL]) #35
|
|
0e76 fc20 bra v6502_next 4020 bra('v6502_next') #36 Retry until sufficient time
|
|
0e77 00ed ld $ed 4021 ld(-38/2) #37
|
|
4022
|
|
4023 # Absolute Modes: $DDDD $DDDD,X $DDDD,Y -- 64 cycles
|
|
4024 label('v6502_modeABS')
|
|
v6502_modeABS:
|
|
0e78 fc7d bra .abs23 4025 bra('.abs23') #21
|
|
0e79 0000 ld $00 4026 ld(0) #22
|
|
4027 label('v6502_modeABX')
|
|
v6502_modeABX:
|
|
0e7a fc7d bra .abs23 4028 bra('.abs23') #21
|
|
4029 label('v6502_modeABY')
|
|
v6502_modeABY:
|
|
0e7b 012a ld [$2a] 4030 ld([v6502_X]) #21,22
|
|
0e7c 012b ld [$2b] 4031 ld([v6502_Y]) #22
|
|
4032 label('.abs23')
|
|
.abs23: 0e7d c224 st [$24] 4033 st([v6502_ADL]) #23
|
|
0e7e 00f3 ld $f3 4034 ld(-64//2+v6502_maxTicks) #24 Is there enough time for the excess ticks?
|
|
0e7f 8115 adda [$15] 4035 adda([vTicks]) #25
|
|
0e80 e86d blt .retry28 4036 blt('.retry28') #26
|
|
0e81 011a ld [$1a] 4037 ld([v6502_PCL]) #27
|
|
0e82 0126 ld [$26] 4038 ld([v6502_IR]) #28 Special case $BE: LDX $DDDD,Y (we got X in ADL)
|
|
0e83 60be xora $be 4039 xora(0xbe) #29
|
|
0e84 f087 beq $0e87 4040 beq(pc()+3) #30
|
|
0e85 fc88 bra $0e88 4041 bra(pc()+3) #31
|
|
0e86 0124 ld [$24] 4042 ld([v6502_ADL]) #32
|
|
0e87 012b ld [$2b] 4043 ld([v6502_Y]) #32(!)
|
|
0e88 8d00 adda [y,x] 4044 adda([Y,X]) #33 Fetch and add L
|
|
0e89 c224 st [$24] 4045 st([v6502_ADL]) #34
|
|
0e8a e88e blt .abs37 4046 bmi('.abs37') #35 Carry?
|
|
0e8b ad00 suba [y,x] 4047 suba([Y,X]) #36 Gets back original operand
|
|
0e8c fc90 bra .abs39 4048 bra('.abs39') #37
|
|
0e8d 4d00 ora [y,x] 4049 ora([Y,X]) #38 Carry in bit 7
|
|
4050 label('.abs37')
|
|
.abs37: 0e8e 2d00 anda [y,x] 4051 anda([Y,X]) #37 Carry in bit 7
|
|
0e8f 0200 nop 4052 nop() #38
|
|
4053 label('.abs39')
|
|
.abs39: 0e90 3080 anda $80,x 4054 anda(0x80,X) #39 Move carry to bit 0
|
|
0e91 0500 ld [x] 4055 ld([X]) #40
|
|
0e92 c225 st [$25] 4056 st([v6502_ADH]) #41
|
|
0e93 011a ld [$1a] 4057 ld([v6502_PCL]) #42 PC++
|
|
0e94 8001 adda $01 4058 adda(1) #43
|
|
0e95 d21a st [$1a],x 4059 st([v6502_PCL],X) #44
|
|
0e96 f099 beq $0e99 4060 beq(pc()+3) #45
|
|
0e97 fc9a bra $0e9a 4061 bra(pc()+3) #46
|
|
0e98 0000 ld $00 4062 ld(0) #47
|
|
0e99 0001 ld $01 4063 ld(1) #47(!)
|
|
0e9a 811b adda [$1b] 4064 adda([v6502_PCH]) #48
|
|
0e9b d61b st [$1b],y 4065 st([v6502_PCH],Y) #49
|
|
0e9c 0d00 ld [y,x] 4066 ld([Y,X]) #50 Fetch H
|
|
0e9d 8125 adda [$25] 4067 adda([v6502_ADH]) #51
|
|
0e9e c225 st [$25] 4068 st([v6502_ADH]) #52
|
|
0e9f 011a ld [$1a] 4069 ld([v6502_PCL]) #53 PC++
|
|
0ea0 8001 adda $01 4070 adda(1) #54
|
|
0ea1 c21a st [$1a] 4071 st([v6502_PCL]) #55
|
|
0ea2 f0a5 beq $0ea5 4072 beq(pc()+3) #56
|
|
0ea3 fca6 bra $0ea6 4073 bra(pc()+3) #57
|
|
0ea4 0000 ld $00 4074 ld(0) #58
|
|
0ea5 0001 ld $01 4075 ld(1) #58(!)
|
|
0ea6 811b adda [$1b] 4076 adda([v6502_PCH]) #59
|
|
0ea7 c21b st [$1b] 4077 st([v6502_PCH]) #60
|
|
0ea8 1124 ld [$24],x 4078 ld([v6502_ADL],X) #61
|
|
0ea9 fcf2 bra v6502_check 4079 bra('v6502_check') #62
|
|
0eaa 00e0 ld $e0 4080 ld(-64/2) #63
|
|
4081
|
|
4082 # Indirect Indexed Mode: ($DD),Y -- 54 cycles
|
|
4083 label('v6502_modeIZY')
|
|
v6502_modeIZY:
|
|
0eab 1200 ld ac,x 4084 ld(AC,X) #21 $DD
|
|
0eac 1400 ld $00,y 4085 ld(0,Y) #22 $00DD
|
|
0ead 00f8 ld $f8 4086 ld(-54//2+v6502_maxTicks) #23 Is there enough time for the excess ticks?
|
|
0eae 8115 adda [$15] 4087 adda([vTicks]) #24
|
|
0eaf 0200 nop 4088 nop() #25
|
|
0eb0 e86d blt .retry28 4089 blt('.retry28') #26
|
|
0eb1 011a ld [$1a] 4090 ld([v6502_PCL]) #27
|
|
0eb2 8001 adda $01 4091 adda(1) #28 PC++
|
|
0eb3 c21a st [$1a] 4092 st([v6502_PCL]) #29
|
|
0eb4 f0b7 beq $0eb7 4093 beq(pc()+3) #30
|
|
0eb5 fcb8 bra $0eb8 4094 bra(pc()+3) #31
|
|
0eb6 0000 ld $00 4095 ld(0) #32
|
|
0eb7 0001 ld $01 4096 ld(1) #32(!)
|
|
0eb8 811b adda [$1b] 4097 adda([v6502_PCH]) #33
|
|
0eb9 c21b st [$1b] 4098 st([v6502_PCH]) #34
|
|
0eba 0d00 ld [y,x] 4099 ld([Y,X]) #35 Read word from zero-page
|
|
0ebb de00 st [y,x++] 4100 st([Y,Xpp]) #36 (Just X++) Wrap-around is correct
|
|
0ebc c224 st [$24] 4101 st([v6502_ADL]) #37
|
|
0ebd 0d00 ld [y,x] 4102 ld([Y,X]) #38
|
|
0ebe c225 st [$25] 4103 st([v6502_ADH]) #39
|
|
0ebf 012b ld [$2b] 4104 ld([v6502_Y]) #40 Add Y
|
|
0ec0 8124 adda [$24] 4105 adda([v6502_ADL]) #41
|
|
0ec1 c224 st [$24] 4106 st([v6502_ADL]) #42
|
|
0ec2 e8c6 blt .izy45 4107 bmi('.izy45') #43 Carry?
|
|
0ec3 a12b suba [$2b] 4108 suba([v6502_Y]) #44 Gets back original operand
|
|
0ec4 fcc8 bra .izy47 4109 bra('.izy47') #45
|
|
0ec5 412b ora [$2b] 4110 ora([v6502_Y]) #46 Carry in bit 7
|
|
4111 label('.izy45')
|
|
.izy45: 0ec6 212b anda [$2b] 4112 anda([v6502_Y]) #45 Carry in bit 7
|
|
0ec7 0200 nop 4113 nop() #46
|
|
4114 label('.izy47')
|
|
.izy47: 0ec8 3080 anda $80,x 4115 anda(0x80,X) #47 Move carry to bit 0
|
|
0ec9 0500 ld [x] 4116 ld([X]) #48
|
|
0eca 8125 adda [$25] 4117 adda([v6502_ADH]) #49
|
|
0ecb c225 st [$25] 4118 st([v6502_ADH]) #50
|
|
0ecc 1124 ld [$24],x 4119 ld([v6502_ADL],X) #51
|
|
0ecd fcf2 bra v6502_check 4120 bra('v6502_check') #52
|
|
0ece 00e5 ld $e5 4121 ld(-54/2) #53
|
|
4122
|
|
4123 # Relative Mode: BEQ BNE BPL BMI BCC BCS BVC BVS -- 36 cycles
|
|
4124 label('v6502_modeREL')
|
|
v6502_modeREL:
|
|
0ecf d224 st [$24],x 4125 st([v6502_ADL],X) #21 Offset (Only needed for branch)
|
|
0ed0 e8d3 blt $0ed3 4126 bmi(pc()+3) #22 Sign extend
|
|
0ed1 fcd4 bra $0ed4 4127 bra(pc()+3) #23
|
|
0ed2 0000 ld $00 4128 ld(0) #24
|
|
0ed3 00ff ld $ff 4129 ld(255) #24(!)
|
|
0ed4 c225 st [$25] 4130 st([v6502_ADH]) #25
|
|
0ed5 011a ld [$1a] 4131 ld([v6502_PCL]) #26 PC++ (Needed for both cases)
|
|
0ed6 8001 adda $01 4132 adda(1) #27
|
|
0ed7 c21a st [$1a] 4133 st([v6502_PCL]) #28
|
|
0ed8 f0db beq $0edb 4134 beq(pc()+3) #29
|
|
0ed9 fcdc bra $0edc 4135 bra(pc()+3) #30
|
|
0eda 0000 ld $00 4136 ld(0) #31
|
|
0edb 0001 ld $01 4137 ld(1) #31(!)
|
|
0edc 811b adda [$1b] 4138 adda([v6502_PCH]) #32
|
|
0edd c21b st [$1b] 4139 st([v6502_PCH]) #33
|
|
0ede fcf2 bra v6502_check 4140 bra('v6502_check') #34
|
|
0edf 00ee ld $ee 4141 ld(-36/2) #53
|
|
4142
|
|
4143 # Indexed Indirect Mode: ($DD,X) -- 38 cycles
|
|
4144 label('v6502_modeIZX')
|
|
v6502_modeIZX:
|
|
0ee0 812a adda [$2a] 4145 adda([v6502_X]) #21 Add X
|
|
0ee1 c21d st [$1d] 4146 st([v6502_Tmp]) #22
|
|
0ee2 9001 adda $01,x 4147 adda(1,X) #23 Read word from zero-page
|
|
0ee3 0500 ld [x] 4148 ld([X]) #24
|
|
0ee4 c225 st [$25] 4149 st([v6502_ADH]) #25
|
|
0ee5 111d ld [$1d],x 4150 ld([v6502_Tmp],X) #26
|
|
0ee6 0500 ld [x] 4151 ld([X]) #27
|
|
0ee7 d224 st [$24],x 4152 st([v6502_ADL],X) #28
|
|
0ee8 011a ld [$1a] 4153 ld([v6502_PCL]) #29 PC++
|
|
0ee9 8001 adda $01 4154 adda(1) #30
|
|
0eea c21a st [$1a] 4155 st([v6502_PCL]) #31
|
|
0eeb f0ee beq $0eee 4156 beq(pc()+3) #32
|
|
0eec fcef bra $0eef 4157 bra(pc()+3) #33
|
|
0eed 0000 ld $00 4158 ld(0) #34
|
|
0eee 0001 ld $01 4159 ld(1) #34(!)
|
|
0eef 811b adda [$1b] 4160 adda([v6502_PCH]) #35
|
|
0ef0 c21b st [$1b] 4161 st([v6502_PCH]) #36
|
|
0ef1 00ed ld $ed 4162 ld(-38/2) #37 !!! Fall through to v6502_check !!!
|
|
4163 #
|
|
4164 # Update elapsed time for the addressing mode processing.
|
|
4165 # Then check if we can immediately execute this instruction.
|
|
4166 # Otherwise transfer control to the video driver.
|
|
4167 label('v6502_check')
|
|
v6502_check: 0ef2 8115 adda [$15] 4168 adda([vTicks]) #0
|
|
4169 blt('v6502_exitAfter') #1 No more ticks
|
|
0ef3 e8f8 blt v6502_exitAfter
|
|
0ef4 c215 st [$15] 4170 st([vTicks]) #2
|
|
0ef5 140f ld $0f,y 4171 ld(hi('v6502_execute'),Y) #3
|
|
0ef6 e126 jmp y,[$26] 4172 jmp(Y,[v6502_IR]) #4
|
|
0ef7 fcff bra $ff 4173 bra(255) #5
|
|
4174
|
|
4175 # Otherwise resync with video driver. At this point we're returning AFTER
|
|
4176 # addressing mode decoding, but before executing the instruction.
|
|
4177 label('v6502_exitAfter')
|
|
v6502_exitAfter:
|
|
0ef8 8013 adda $13 4178 adda(v6502_maxTicks) #3 Exit AFTER fetch
|
|
0ef9 e4f9 bgt $0ef9 4179 bgt(pc()&255) #4 Resync
|
|
0efa a001 suba $01 4180 suba(1) #5
|
|
0efb 0010 ld $10 4181 ld(hi('v6502_RESUME')) #6 Set entry point to before 'execute'
|
|
0efc c205 st [$05] 4182 st([vCpuSelect]) #7
|
|
0efd 1401 ld $01,y 4183 ld(hi('vBlankStart'),Y) #8
|
|
0efe e11e jmp y,[$1e] 4184 jmp(Y,[vReturn]) #9 To video driver
|
|
0eff 0000 ld $00 4185 ld(0) #10
|
|
4186 assert v6502_overhead == 11
|
|
4187
|
|
4188 align(0x100,size=0x100)
|
|
4189 label('v6502_execute')
|
|
4190 # This page works as a 255-entry (0..254) jump table for 6502 opcodes.
|
|
4191 # Jumping into this page must have 'bra 255' in the branch delay slot
|
|
4192 # in order to get out again and dispatch to the right continuation.
|
|
4193 # X must hold [v6502_ADL],
|
|
4194 # Y will hold hi('v6502_execute'),
|
|
4195 # A will be loaded with the code offset (this is skipped at offset $ff)
|
|
v6502_execute:
|
|
0f00 00fd ld $fd 4196 ld('v6502_BRK'); ld('v6502_ORA'); ld('v6502_ILL'); ld('v6502_ILL') #6 $00
|
|
0f01 0089 ld $89
|
|
0f02 00fd ld $fd
|
|
0f03 00fd ld $fd
|
|
0f04 00fd ld $fd 4197 ld('v6502_ILL'); ld('v6502_ORA'); ld('v6502_ASL'); ld('v6502_ILL') #6
|
|
0f05 0089 ld $89
|
|
0f06 00f1 ld $f1
|
|
0f07 00fd ld $fd
|
|
0f08 00f3 ld $f3 4198 ld('v6502_PHP'); ld('v6502_ORA'); ld('v6502_ASL'); ld('v6502_ILL') #6
|
|
0f09 0089 ld $89
|
|
0f0a 00f1 ld $f1
|
|
0f0b 00fd ld $fd
|
|
0f0c 00fd ld $fd 4199 ld('v6502_ILL'); ld('v6502_ORA'); ld('v6502_ASL'); ld('v6502_ILL') #6
|
|
0f0d 0089 ld $89
|
|
0f0e 00f1 ld $f1
|
|
0f0f 00fd ld $fd
|
|
0f10 003f ld $3f 4200 ld('v6502_BPL'); ld('v6502_ORA'); ld('v6502_ILL'); ld('v6502_ILL') #6 $10
|
|
0f11 0089 ld $89
|
|
0f12 00fd ld $fd
|
|
0f13 00fd ld $fd
|
|
0f14 00fd ld $fd 4201 ld('v6502_ILL'); ld('v6502_ORA'); ld('v6502_ASL'); ld('v6502_ILL') #6
|
|
0f15 0089 ld $89
|
|
0f16 00f1 ld $f1
|
|
0f17 00fd ld $fd
|
|
0f18 0036 ld $36 4202 ld('v6502_CLC'); ld('v6502_ORA'); ld('v6502_ILL'); ld('v6502_ILL') #6
|
|
0f19 0089 ld $89
|
|
0f1a 00fd ld $fd
|
|
0f1b 00fd ld $fd
|
|
0f1c 00fd ld $fd 4203 ld('v6502_ILL'); ld('v6502_ORA'); ld('v6502_ASL'); ld('v6502_ILL') #6
|
|
0f1d 0089 ld $89
|
|
0f1e 00f1 ld $f1
|
|
0f1f 00fd ld $fd
|
|
0f20 009a ld $9a 4204 ld('v6502_JSR'); ld('v6502_AND'); ld('v6502_ILL'); ld('v6502_ILL') #6 $20
|
|
0f21 0085 ld $85
|
|
0f22 00fd ld $fd
|
|
0f23 00fd ld $fd
|
|
0f24 00f5 ld $f5 4205 ld('v6502_BIT'); ld('v6502_AND'); ld('v6502_ROL'); ld('v6502_ILL') #6
|
|
0f25 0085 ld $85
|
|
0f26 00f7 ld $f7
|
|
0f27 00fd ld $fd
|
|
0f28 00f9 ld $f9 4206 ld('v6502_PLP'); ld('v6502_AND'); ld('v6502_ROL'); ld('v6502_ILL') #6
|
|
0f29 0085 ld $85
|
|
0f2a 00f7 ld $f7
|
|
0f2b 00fd ld $fd
|
|
0f2c 00f5 ld $f5 4207 ld('v6502_BIT'); ld('v6502_AND'); ld('v6502_ROL'); ld('v6502_ILL') #6
|
|
0f2d 0085 ld $85
|
|
0f2e 00f7 ld $f7
|
|
0f2f 00fd ld $fd
|
|
0f30 0042 ld $42 4208 ld('v6502_BMI'); ld('v6502_AND'); ld('v6502_ILL'); ld('v6502_ILL') #6 $30
|
|
0f31 0085 ld $85
|
|
0f32 00fd ld $fd
|
|
0f33 00fd ld $fd
|
|
0f34 00fd ld $fd 4209 ld('v6502_ILL'); ld('v6502_AND'); ld('v6502_ROL'); ld('v6502_ILL') #6
|
|
0f35 0085 ld $85
|
|
0f36 00f7 ld $f7
|
|
0f37 00fd ld $fd
|
|
0f38 0038 ld $38 4210 ld('v6502_SEC'); ld('v6502_AND'); ld('v6502_ILL'); ld('v6502_ILL') #6
|
|
0f39 0085 ld $85
|
|
0f3a 00fd ld $fd
|
|
0f3b 00fd ld $fd
|
|
0f3c 00fd ld $fd 4211 ld('v6502_ILL'); ld('v6502_AND'); ld('v6502_ROL'); ld('v6502_ILL') #6
|
|
0f3d 0085 ld $85
|
|
0f3e 00f7 ld $f7
|
|
0f3f 00fd ld $fd
|
|
0f40 00d3 ld $d3 4212 ld('v6502_RTI'); ld('v6502_EOR'); ld('v6502_ILL'); ld('v6502_ILL') #6 $40
|
|
0f41 008c ld $8c
|
|
0f42 00fd ld $fd
|
|
0f43 00fd ld $fd
|
|
0f44 00fd ld $fd 4213 ld('v6502_ILL'); ld('v6502_EOR'); ld('v6502_LSR'); ld('v6502_ILL') #6
|
|
0f45 008c ld $8c
|
|
0f46 00d7 ld $d7
|
|
0f47 00fd ld $fd
|
|
0f48 00d9 ld $d9 4214 ld('v6502_PHA'); ld('v6502_EOR'); ld('v6502_LSR'); ld('v6502_ILL') #6
|
|
0f49 008c ld $8c
|
|
0f4a 00d7 ld $d7
|
|
0f4b 00fd ld $fd
|
|
0f4c 0096 ld $96 4215 ld('v6502_JMP1');ld('v6502_EOR'); ld('v6502_LSR'); ld('v6502_ILL') #6
|
|
0f4d 008c ld $8c
|
|
0f4e 00d7 ld $d7
|
|
0f4f 00fd ld $fd
|
|
0f50 0045 ld $45 4216 ld('v6502_BVC'); ld('v6502_EOR'); ld('v6502_ILL'); ld('v6502_ILL') #6 $50
|
|
0f51 008c ld $8c
|
|
0f52 00fd ld $fd
|
|
0f53 00fd ld $fd
|
|
0f54 00fd ld $fd 4217 ld('v6502_ILL'); ld('v6502_EOR'); ld('v6502_LSR'); ld('v6502_ILL') #6
|
|
0f55 008c ld $8c
|
|
0f56 00d7 ld $d7
|
|
0f57 00fd ld $fd
|
|
0f58 00db ld $db 4218 ld('v6502_CLI'); ld('v6502_EOR'); ld('v6502_ILL'); ld('v6502_ILL') #6
|
|
0f59 008c ld $8c
|
|
0f5a 00fd ld $fd
|
|
0f5b 00fd ld $fd
|
|
0f5c 00fd ld $fd 4219 ld('v6502_ILL'); ld('v6502_EOR'); ld('v6502_LSR'); ld('v6502_ILL') #6
|
|
0f5d 008c ld $8c
|
|
0f5e 00d7 ld $d7
|
|
0f5f 00fd ld $fd
|
|
0f60 00dd ld $dd 4220 ld('v6502_RTS'); ld('v6502_ADC'); ld('v6502_ILL'); ld('v6502_ILL') #6 $60
|
|
0f61 0001 ld $01
|
|
0f62 00fd ld $fd
|
|
0f63 00fd ld $fd
|
|
0f64 00fd ld $fd 4221 ld('v6502_ILL'); ld('v6502_ADC'); ld('v6502_ROR'); ld('v6502_ILL') #6
|
|
0f65 0001 ld $01
|
|
0f66 00d5 ld $d5
|
|
0f67 00fd ld $fd
|
|
0f68 00df ld $df 4222 ld('v6502_PLA'); ld('v6502_ADC'); ld('v6502_ROR'); ld('v6502_ILL') #6
|
|
0f69 0001 ld $01
|
|
0f6a 00d5 ld $d5
|
|
0f6b 00fd ld $fd
|
|
0f6c 0098 ld $98 4223 ld('v6502_JMP2');ld('v6502_ADC'); ld('v6502_ROR'); ld('v6502_ILL') #6
|
|
0f6d 0001 ld $01
|
|
0f6e 00d5 ld $d5
|
|
0f6f 00fd ld $fd
|
|
0f70 0049 ld $49 4224 ld('v6502_BVS'); ld('v6502_ADC'); ld('v6502_ILL'); ld('v6502_ILL') #6 $70
|
|
0f71 0001 ld $01
|
|
0f72 00fd ld $fd
|
|
0f73 00fd ld $fd
|
|
0f74 00fd ld $fd 4225 ld('v6502_ILL'); ld('v6502_ADC'); ld('v6502_ROR'); ld('v6502_ILL') #6
|
|
0f75 0001 ld $01
|
|
0f76 00d5 ld $d5
|
|
0f77 00fd ld $fd
|
|
0f78 00e1 ld $e1 4226 ld('v6502_SEI'); ld('v6502_ADC'); ld('v6502_ILL'); ld('v6502_ILL') #6
|
|
0f79 0001 ld $01
|
|
0f7a 00fd ld $fd
|
|
0f7b 00fd ld $fd
|
|
0f7c 00fd ld $fd 4227 ld('v6502_ILL'); ld('v6502_ADC'); ld('v6502_ROR'); ld('v6502_ILL') #6
|
|
0f7d 0001 ld $01
|
|
0f7e 00d5 ld $d5
|
|
0f7f 00fd ld $fd
|
|
0f80 00fd ld $fd 4228 ld('v6502_ILL'); ld('v6502_STA'); ld('v6502_ILL'); ld('v6502_ILL') #6 $80
|
|
0f81 00c1 ld $c1
|
|
0f82 00fd ld $fd
|
|
0f83 00fd ld $fd
|
|
0f84 00c7 ld $c7 4229 ld('v6502_STY'); ld('v6502_STA'); ld('v6502_STX'); ld('v6502_ILL') #6
|
|
0f85 00c1 ld $c1
|
|
0f86 00c3 ld $c3
|
|
0f87 00fd ld $fd
|
|
0f88 007f ld $7f 4230 ld('v6502_DEY'); ld('v6502_ILL'); ld('v6502_TXA'); ld('v6502_ILL') #6
|
|
0f89 00fd ld $fd
|
|
0f8a 00cd ld $cd
|
|
0f8b 00fd ld $fd
|
|
0f8c 00c7 ld $c7 4231 ld('v6502_STY'); ld('v6502_STA'); ld('v6502_STX'); ld('v6502_ILL') #6
|
|
0f8d 00c1 ld $c1
|
|
0f8e 00c3 ld $c3
|
|
0f8f 00fd ld $fd
|
|
0f90 004d ld $4d 4232 ld('v6502_BCC'); ld('v6502_STA'); ld('v6502_ILL'); ld('v6502_ILL') #6 $90
|
|
0f91 00c1 ld $c1
|
|
0f92 00fd ld $fd
|
|
0f93 00fd ld $fd
|
|
0f94 00c7 ld $c7 4233 ld('v6502_STY'); ld('v6502_STA'); ld('v6502_STX2');ld('v6502_ILL') #6
|
|
0f95 00c1 ld $c1
|
|
0f96 00c5 ld $c5
|
|
0f97 00fd ld $fd
|
|
0f98 00cf ld $cf 4234 ld('v6502_TYA'); ld('v6502_STA'); ld('v6502_TXS'); ld('v6502_ILL') #6
|
|
0f99 00c1 ld $c1
|
|
0f9a 00e3 ld $e3
|
|
0f9b 00fd ld $fd
|
|
0f9c 00fd ld $fd 4235 ld('v6502_ILL'); ld('v6502_STA'); ld('v6502_ILL'); ld('v6502_ILL') #6
|
|
0f9d 00c1 ld $c1
|
|
0f9e 00fd ld $fd
|
|
0f9f 00fd ld $fd
|
|
0fa0 00bf ld $bf 4236 ld('v6502_LDY'); ld('v6502_LDA'); ld('v6502_LDX'); ld('v6502_ILL') #6 $A0
|
|
0fa1 00b9 ld $b9
|
|
0fa2 00bb ld $bb
|
|
0fa3 00fd ld $fd
|
|
0fa4 00bf ld $bf 4237 ld('v6502_LDY'); ld('v6502_LDA'); ld('v6502_LDX'); ld('v6502_ILL') #6
|
|
0fa5 00b9 ld $b9
|
|
0fa6 00bb ld $bb
|
|
0fa7 00fd ld $fd
|
|
0fa8 00cb ld $cb 4238 ld('v6502_TAY'); ld('v6502_LDA'); ld('v6502_TAX'); ld('v6502_ILL') #6
|
|
0fa9 00b9 ld $b9
|
|
0faa 00c9 ld $c9
|
|
0fab 00fd ld $fd
|
|
0fac 00bf ld $bf 4239 ld('v6502_LDY'); ld('v6502_LDA'); ld('v6502_LDX'); ld('v6502_ILL') #6
|
|
0fad 00b9 ld $b9
|
|
0fae 00bb ld $bb
|
|
0faf 00fd ld $fd
|
|
0fb0 0051 ld $51 4240 ld('v6502_BCS'); ld('v6502_LDA'); ld('v6502_ILL'); ld('v6502_ILL') #6 $B0
|
|
0fb1 00b9 ld $b9
|
|
0fb2 00fd ld $fd
|
|
0fb3 00fd ld $fd
|
|
0fb4 00bf ld $bf 4241 ld('v6502_LDY'); ld('v6502_LDA'); ld('v6502_LDX2');ld('v6502_ILL') #6
|
|
0fb5 00b9 ld $b9
|
|
0fb6 00bd ld $bd
|
|
0fb7 00fd ld $fd
|
|
0fb8 00d1 ld $d1 4242 ld('v6502_CLV'); ld('v6502_LDA'); ld('v6502_TSX'); ld('v6502_ILL') #6
|
|
0fb9 00b9 ld $b9
|
|
0fba 00e5 ld $e5
|
|
0fbb 00fd ld $fd
|
|
0fbc 00bf ld $bf 4243 ld('v6502_LDY'); ld('v6502_LDA'); ld('v6502_LDX'); ld('v6502_ILL') #6
|
|
0fbd 00b9 ld $b9
|
|
0fbe 00bb ld $bb
|
|
0fbf 00fd ld $fd
|
|
0fc0 00e7 ld $e7 4244 ld('v6502_CPY'); ld('v6502_CMP'); ld('v6502_ILL'); ld('v6502_ILL') #6 $C0
|
|
0fc1 00e9 ld $e9
|
|
0fc2 00fd ld $fd
|
|
0fc3 00fd ld $fd
|
|
0fc4 00e7 ld $e7 4245 ld('v6502_CPY'); ld('v6502_CMP'); ld('v6502_DEC'); ld('v6502_ILL') #6
|
|
0fc5 00e9 ld $e9
|
|
0fc6 00eb ld $eb
|
|
0fc7 00fd ld $fd
|
|
0fc8 007b ld $7b 4246 ld('v6502_INY'); ld('v6502_CMP'); ld('v6502_DEX'); ld('v6502_ILL') #6
|
|
0fc9 00e9 ld $e9
|
|
0fca 0077 ld $77
|
|
0fcb 00fd ld $fd
|
|
0fcc 00e7 ld $e7 4247 ld('v6502_CPY'); ld('v6502_CMP'); ld('v6502_DEC'); ld('v6502_ILL') #6
|
|
0fcd 00e9 ld $e9
|
|
0fce 00eb ld $eb
|
|
0fcf 00fd ld $fd
|
|
0fd0 0055 ld $55 4248 ld('v6502_BNE'); ld('v6502_CMP'); ld('v6502_ILL'); ld('v6502_ILL') #6 $D0
|
|
0fd1 00e9 ld $e9
|
|
0fd2 00fd ld $fd
|
|
0fd3 00fd ld $fd
|
|
0fd4 00fd ld $fd 4249 ld('v6502_ILL'); ld('v6502_CMP'); ld('v6502_DEC'); ld('v6502_ILL') #6
|
|
0fd5 00e9 ld $e9
|
|
0fd6 00eb ld $eb
|
|
0fd7 00fd ld $fd
|
|
0fd8 00ed ld $ed 4250 ld('v6502_CLD'); ld('v6502_CMP'); ld('v6502_ILL'); ld('v6502_ILL') #6
|
|
0fd9 00e9 ld $e9
|
|
0fda 00fd ld $fd
|
|
0fdb 00fd ld $fd
|
|
0fdc 00fd ld $fd 4251 ld('v6502_ILL'); ld('v6502_CMP'); ld('v6502_DEC'); ld('v6502_ILL') #6
|
|
0fdd 00e9 ld $e9
|
|
0fde 00eb ld $eb
|
|
0fdf 00fd ld $fd
|
|
0fe0 00ef ld $ef 4252 ld('v6502_CPX'); ld('v6502_SBC'); ld('v6502_ILL'); ld('v6502_ILL') #6 $E0
|
|
0fe1 0029 ld $29
|
|
0fe2 00fd ld $fd
|
|
0fe3 00fd ld $fd
|
|
0fe4 00ef ld $ef 4253 ld('v6502_CPX'); ld('v6502_SBC'); ld('v6502_INC'); ld('v6502_ILL') #6
|
|
0fe5 0029 ld $29
|
|
0fe6 00b7 ld $b7
|
|
0fe7 00fd ld $fd
|
|
0fe8 006c ld $6c 4254 ld('v6502_INX'); ld('v6502_SBC'); ld('v6502_NOP'); ld('v6502_ILL') #6
|
|
0fe9 0029 ld $29
|
|
0fea 0083 ld $83
|
|
0feb 00fd ld $fd
|
|
0fec 00ef ld $ef 4255 ld('v6502_CPX'); ld('v6502_SBC'); ld('v6502_INC'); ld('v6502_ILL') #6
|
|
0fed 0029 ld $29
|
|
0fee 00b7 ld $b7
|
|
0fef 00fd ld $fd
|
|
0ff0 0058 ld $58 4256 ld('v6502_BEQ'); ld('v6502_SBC'); ld('v6502_ILL'); ld('v6502_ILL') #6 $F0
|
|
0ff1 0029 ld $29
|
|
0ff2 00fd ld $fd
|
|
0ff3 00fd ld $fd
|
|
0ff4 00fd ld $fd 4257 ld('v6502_ILL'); ld('v6502_SBC'); ld('v6502_INC'); ld('v6502_ILL') #6
|
|
0ff5 0029 ld $29
|
|
0ff6 00b7 ld $b7
|
|
0ff7 00fd ld $fd
|
|
0ff8 00fb ld $fb 4258 ld('v6502_SED'); ld('v6502_SBC'); ld('v6502_ILL'); ld('v6502_ILL') #6
|
|
0ff9 0029 ld $29
|
|
0ffa 00fd ld $fd
|
|
0ffb 00fd ld $fd
|
|
0ffc 00fd ld $fd 4259 ld('v6502_ILL'); ld('v6502_SBC'); ld('v6502_INC') #6
|
|
0ffd 0029 ld $29
|
|
0ffe 00b7 ld $b7
|
|
0fff fe00 bra ac 4260 bra(AC) #6,7 Dispatch into next page
|
|
4261 # --- Page boundary ---
|
|
4262 align(0x100,size=0x100)
|
|
1000 140e ld $0e,y 4263 ld(hi('v6502_next'),Y) #8 Handy for instructions that don't clobber Y
|
|
4264
|
|
4265 label('v6502_ADC')
|
|
4266 assert pc()&255 == 1
|
|
4267 assert v6502_Cflag == 1
|
|
4268 assert v6502_Vemu == 128
|
|
v6502_ADC: 1001 1525 ld [$25],y 4269 ld([v6502_ADH],Y) #9 Must be at page offset 1, so A=1
|
|
1002 2127 anda [$27] 4270 anda([v6502_P]) #10 Carry in (AC=1 because lo('v6502_ADC')=1)
|
|
1003 8118 adda [$18] 4271 adda([v6502_A]) #11 Sum
|
|
1004 f020 beq .adc14 4272 beq('.adc14') #12 Danger zone for dropping a carry
|
|
1005 8d00 adda [y,x] 4273 adda([Y,X]) #13
|
|
1006 c228 st [$28] 4274 st([v6502_Qz]) #14 Z flag, don't overwrite left-hand side (A) yet
|
|
1007 c229 st [$29] 4275 st([v6502_Qn]) #15 N flag
|
|
1008 6118 xora [$18] 4276 xora([v6502_A]) #16 V flag, (Q^A) & (B^Q) & 0x80
|
|
1009 c218 st [$18] 4277 st([v6502_A]) #17
|
|
100a 0d00 ld [y,x] 4278 ld([Y,X]) #18
|
|
100b 6128 xora [$28] 4279 xora([v6502_Qz]) #19
|
|
100c 2118 anda [$18] 4280 anda([v6502_A]) #20
|
|
100d 2080 anda $80 4281 anda(0x80) #21
|
|
100e c21d st [$1d] 4282 st([v6502_Tmp]) #22
|
|
100f 0128 ld [$28] 4283 ld([v6502_Qz]) #23 Update A
|
|
1010 c218 st [$18] 4284 st([v6502_A]) #24
|
|
1011 e815 blt .adc27 4285 bmi('.adc27') #25 C flag
|
|
1012 ad00 suba [y,x] 4286 suba([Y,X]) #26
|
|
1013 fc17 bra .adc29 4287 bra('.adc29') #27
|
|
1014 4d00 ora [y,x] 4288 ora([Y,X]) #28
|
|
4289 label('.adc27')
|
|
.adc27: 1015 2d00 anda [y,x] 4290 anda([Y,X]) #27
|
|
1016 0200 nop 4291 nop() #28
|
|
4292 label('.adc29')
|
|
.adc29: 1017 3080 anda $80,x 4293 anda(0x80,X) #29
|
|
1018 0127 ld [$27] 4294 ld([v6502_P]) #30 Update P
|
|
1019 207e anda $7e 4295 anda(~v6502_Vemu&~v6502_Cflag) #31
|
|
101a 4500 ora [x] 4296 ora([X]) #32
|
|
101b 411d ora [$1d] 4297 ora([v6502_Tmp]) #33
|
|
101c c227 st [$27] 4298 st([v6502_P]) #34
|
|
101d 140e ld $0e,y 4299 ld(hi('v6502_next'),Y) #35
|
|
101e e020 jmp y,$20 4300 jmp(Y,'v6502_next') #36
|
|
101f 00ed ld $ed 4301 ld(-38/2) #37
|
|
4302 # Cin=1, A=$FF, B=$DD --> Result=$DD, Cout=1, V=0
|
|
4303 # Cin=0, A=$00, B=$DD --> Result=$DD, Cout=0, V=0
|
|
4304 label('.adc14')
|
|
.adc14: 1020 c218 st [$18] 4305 st([v6502_A]) #14 Special case
|
|
1021 c228 st [$28] 4306 st([v6502_Qz]) #15 Z flag
|
|
1022 c229 st [$29] 4307 st([v6502_Qn]) #16 N flag
|
|
1023 0127 ld [$27] 4308 ld([v6502_P]) #17
|
|
1024 207f anda $7f 4309 anda(0x7f) #18 V=0, keep C
|
|
1025 c227 st [$27] 4310 st([v6502_P]) #19
|
|
1026 140e ld $0e,y 4311 ld(hi('v6502_next'),Y) #20
|
|
1027 00f4 ld $f4 4312 ld(-24/2) #21
|
|
1028 e020 jmp y,$20 4313 jmp(Y,'v6502_next') #22
|
|
4314 #nop() #23 Overlap
|
|
4315 #
|
|
4316 label('v6502_SBC')
|
|
4317 # No matter how hard we try, v6502_SBC always comes out a lot clumsier
|
|
4318 # than v6502_ADC. And that one already barely fits in 38 cycles and is
|
|
4319 # hard to follow. So we use a hack: transmorph our SBC into an ADC with
|
|
4320 # inverted operand, and then dispatch again. Simple and effective.
|
|
v6502_SBC: 1029 1525 ld [$25],y 4321 ld([v6502_ADH],Y) #9,24
|
|
102a 0d00 ld [y,x] 4322 ld([Y,X]) #10
|
|
102b 60ff xora $ff 4323 xora(255) #11 Invert right-hand side operand
|
|
102c c219 st [$19] 4324 st([v6502_BI]) #12 Park modified operand for v6502_ADC
|
|
102d 0019 ld $19 4325 ld(v6502_BI&255) #13 Address of BI
|
|
102e d224 st [$24],x 4326 st([v6502_ADL],X) #14
|
|
102f 0000 ld $00 4327 ld(v6502_BI>>8) #15
|
|
1030 c225 st [$25] 4328 st([v6502_ADH]) #16
|
|
1031 0069 ld $69 4329 ld(0x69) #17 ADC #$xx (Any ADC opcode will do)
|
|
1032 c226 st [$26] 4330 st([v6502_IR]) #18
|
|
1033 140e ld $0e,y 4331 ld(hi('v6502_check'),Y) #20 Go back to time check before dispatch
|
|
1034 e0f2 jmp y,$f2 4332 jmp(Y,'v6502_check') #20
|
|
1035 00f5 ld $f5 4333 ld(-22/2) #21
|
|
4334
|
|
4335 # Carry calculation table
|
|
4336 # L7 R7 C7 RX UC SC
|
|
4337 # -- -- -- | -- -- --
|
|
4338 # 0 0 0 | 0 0 0
|
|
4339 # 0 0 1 | 0 0 0
|
|
4340 # 1 0 0 | 0 1 +1
|
|
4341 # 1 0 1 | 0 0 0
|
|
4342 # 0 1 0 | -1 1 0
|
|
4343 # 0 1 1 | -1 0 -1
|
|
4344 # 1 1 0 | -1 1 0
|
|
4345 # 1 1 1 | -1 1 0
|
|
4346 # -- -- -- | -- -- --
|
|
4347 # ^ ^ ^ ^ ^ ^
|
|
4348 # | | | | | `--- Carry of unsigned L + signed R: SC = RX + UC
|
|
4349 # | | | | `----- Carry of unsigned L + unsigned R: UC = C7 ? L7&R7 : L7|R7
|
|
4350 # | | | `------- Sign extension of signed R
|
|
4351 # | | `--------- MSB of unextended L + R
|
|
4352 # | `----------- MSB of right operand R
|
|
4353 # `------------- MSB of left operand L
|
|
4354
|
|
4355 label('v6502_CLC')
|
|
v6502_CLC: 1036 0127 ld [$27] 4356 ld([v6502_P]) #9
|
|
1037 fc3b bra .sec12 4357 bra('.sec12') #10
|
|
4358 label('v6502_SEC')
|
|
v6502_SEC: 1038 20fe anda $fe 4359 anda(~v6502_Cflag) #9,11 Overlap
|
|
1039 0127 ld [$27] 4360 ld([v6502_P]) #10
|
|
103a 4001 ora $01 4361 ora(v6502_Cflag) #11
|
|
4362 label('.sec12')
|
|
.sec12: 103b c227 st [$27] 4363 st([v6502_P]) #12
|
|
103c 0200 nop 4364 nop() #13
|
|
4365 label('.next14')
|
|
.next14: 103d e020 jmp y,$20 4366 jmp(Y,'v6502_next') #14
|
|
103e 00f8 ld $f8 4367 ld(-16/2) #15
|
|
4368
|
|
4369 label('v6502_BPL')
|
|
v6502_BPL: 103f 0129 ld [$29] 4370 ld([v6502_Qn]) #9
|
|
1040 e875 blt .next12 4371 bmi('.next12') #10
|
|
1041 f45b bge .branch13 4372 bpl('.branch13') #11
|
|
4373 #nop() #12 Overlap
|
|
4374 label('v6502_BMI')
|
|
v6502_BMI: 1042 0129 ld [$29] 4375 ld([v6502_Qn]) #9,12
|
|
1043 f475 bge .next12 4376 bpl('.next12') #10
|
|
1044 e85b blt .branch13 4377 bmi('.branch13') #11
|
|
4378 #nop() #12 Overlap
|
|
4379 label('v6502_BVC')
|
|
v6502_BVC: 1045 0127 ld [$27] 4380 ld([v6502_P]) #9,12
|
|
1046 2080 anda $80 4381 anda(v6502_Vemu) #10
|
|
1047 f05b beq .branch13 4382 beq('.branch13') #11
|
|
1048 ec3d bne .next14 4383 bne('.next14') #12
|
|
4384 #nop() #13 Overlap
|
|
4385 label('v6502_BVS')
|
|
v6502_BVS: 1049 0127 ld [$27] 4386 ld([v6502_P]) #9,13
|
|
104a 2080 anda $80 4387 anda(v6502_Vemu) #10
|
|
104b ec5b bne .branch13 4388 bne('.branch13') #11
|
|
104c f03d beq .next14 4389 beq('.next14') #12
|
|
4390 #nop() #13 Overlap
|
|
4391 label('v6502_BCC')
|
|
v6502_BCC: 104d 0127 ld [$27] 4392 ld([v6502_P]) #9,13
|
|
104e 2001 anda $01 4393 anda(v6502_Cflag) #10
|
|
104f f05b beq .branch13 4394 beq('.branch13') #11
|
|
1050 ec3d bne .next14 4395 bne('.next14') #12
|
|
4396 #nop() #13 Overlap
|
|
4397 label('v6502_BCS')
|
|
v6502_BCS: 1051 0127 ld [$27] 4398 ld([v6502_P]) #9,13
|
|
1052 2001 anda $01 4399 anda(v6502_Cflag) #10
|
|
1053 ec5b bne .branch13 4400 bne('.branch13') #11
|
|
1054 f03d beq .next14 4401 beq('.next14') #12
|
|
4402 #nop() #13 Overlap
|
|
4403 label('v6502_BNE')
|
|
v6502_BNE: 1055 0128 ld [$28] 4404 ld([v6502_Qz]) #9,13
|
|
1056 f075 beq .next12 4405 beq('.next12') #10
|
|
1057 ec5b bne .branch13 4406 bne('.branch13') #11
|
|
4407 #nop() #12 Overlap
|
|
4408 label('v6502_BEQ')
|
|
v6502_BEQ: 1058 0128 ld [$28] 4409 ld([v6502_Qz]) #9,12
|
|
1059 ec75 bne .next12 4410 bne('.next12') #10
|
|
105a f05b beq .branch13 4411 beq('.branch13') #11
|
|
4412 #nop() #12 Overlap
|
|
4413 label('.branch13')
|
|
.branch13: 105b 0124 ld [$24] 4414 ld([v6502_ADL]) #13,12 PC + offset
|
|
105c 811a adda [$1a] 4415 adda([v6502_PCL]) #14
|
|
105d c21a st [$1a] 4416 st([v6502_PCL]) #15
|
|
105e e862 blt .bra0 4417 bmi('.bra0') #16 Carry
|
|
105f a124 suba [$24] 4418 suba([v6502_ADL]) #17
|
|
1060 fc64 bra .bra1 4419 bra('.bra1') #18
|
|
1061 4124 ora [$24] 4420 ora([v6502_ADL]) #19
|
|
4421 label('.bra0')
|
|
.bra0: 1062 2124 anda [$24] 4422 anda([v6502_ADL]) #18
|
|
1063 0200 nop 4423 nop() #19
|
|
4424 label('.bra1')
|
|
.bra1: 1064 3080 anda $80,x 4425 anda(0x80,X) #20
|
|
1065 0500 ld [x] 4426 ld([X]) #21
|
|
1066 8125 adda [$25] 4427 adda([v6502_ADH]) #22
|
|
1067 811b adda [$1b] 4428 adda([v6502_PCH]) #23
|
|
1068 c21b st [$1b] 4429 st([v6502_PCH]) #24
|
|
1069 0200 nop 4430 nop() #25
|
|
106a e020 jmp y,$20 4431 jmp(Y,'v6502_next') #26
|
|
106b 00f2 ld $f2 4432 ld(-28/2) #27
|
|
4433
|
|
4434 label('v6502_INX')
|
|
v6502_INX: 106c 0200 nop 4435 nop() #9
|
|
106d 012a ld [$2a] 4436 ld([v6502_X]) #10
|
|
106e 8001 adda $01 4437 adda(1) #11
|
|
106f c22a st [$2a] 4438 st([v6502_X]) #12
|
|
4439 label('.inx13')
|
|
.inx13: 1070 c228 st [$28] 4440 st([v6502_Qz]) #13 Z flag
|
|
1071 c229 st [$29] 4441 st([v6502_Qn]) #14 N flag
|
|
1072 00f7 ld $f7 4442 ld(-18/2) #15
|
|
1073 e020 jmp y,$20 4443 jmp(Y,'v6502_next') #16
|
|
1074 0200 nop 4444 nop() #17
|
|
4445
|
|
4446 label('.next12')
|
|
.next12: 1075 e020 jmp y,$20 4447 jmp(Y,'v6502_next') #12
|
|
1076 00f9 ld $f9 4448 ld(-14/2) #13
|
|
4449
|
|
4450 label('v6502_DEX')
|
|
v6502_DEX: 1077 012a ld [$2a] 4451 ld([v6502_X]) #9
|
|
1078 a001 suba $01 4452 suba(1) #10
|
|
1079 fc70 bra .inx13 4453 bra('.inx13') #11
|
|
107a c22a st [$2a] 4454 st([v6502_X]) #12
|
|
4455
|
|
4456 label('v6502_INY')
|
|
v6502_INY: 107b 012b ld [$2b] 4457 ld([v6502_Y]) #9
|
|
107c 8001 adda $01 4458 adda(1) #10
|
|
107d fc70 bra .inx13 4459 bra('.inx13') #11
|
|
107e c22b st [$2b] 4460 st([v6502_Y]) #12
|
|
4461
|
|
4462 label('v6502_DEY')
|
|
v6502_DEY: 107f 012b ld [$2b] 4463 ld([v6502_Y]) #9
|
|
1080 a001 suba $01 4464 suba(1) #10
|
|
1081 fc70 bra .inx13 4465 bra('.inx13') #11
|
|
1082 c22b st [$2b] 4466 st([v6502_Y]) #12
|
|
4467
|
|
4468 label('v6502_NOP')
|
|
v6502_NOP: 1083 00fa ld $fa 4469 ld(-12/2) #9
|
|
1084 e020 jmp y,$20 4470 jmp(Y,'v6502_next') #10
|
|
4471 #nop() #11 Overlap
|
|
4472 #
|
|
4473 label('v6502_AND')
|
|
v6502_AND: 1085 1525 ld [$25],y 4474 ld([v6502_ADH],Y) #9,11
|
|
1086 0118 ld [$18] 4475 ld([v6502_A]) #10
|
|
1087 fc90 bra .eor13 4476 bra('.eor13') #11
|
|
1088 2d00 anda [y,x] 4477 anda([Y,X]) #12
|
|
4478
|
|
4479 label('v6502_ORA')
|
|
v6502_ORA: 1089 1525 ld [$25],y 4480 ld([v6502_ADH],Y) #9
|
|
108a 0118 ld [$18] 4481 ld([v6502_A]) #10
|
|
108b fc90 bra .eor13 4482 bra('.eor13') #11
|
|
4483 label('v6502_EOR')
|
|
v6502_EOR: 108c 4d00 ora [y,x] 4484 ora([Y,X]) #12,9
|
|
4485 #
|
|
4486 #label('v6502_EOR')
|
|
4487 #nop() #9 Overlap
|
|
108d 1525 ld [$25],y 4488 ld([v6502_ADH],Y) #10
|
|
108e 0118 ld [$18] 4489 ld([v6502_A]) #11
|
|
108f 6d00 xora [y,x] 4490 xora([Y,X]) #12
|
|
4491 label('.eor13')
|
|
.eor13: 1090 c218 st [$18] 4492 st([v6502_A]) #13
|
|
1091 c228 st [$28] 4493 st([v6502_Qz]) #14 Z flag
|
|
1092 c229 st [$29] 4494 st([v6502_Qn]) #15 N flag
|
|
1093 140e ld $0e,y 4495 ld(hi('v6502_next'),Y) #16
|
|
1094 00f6 ld $f6 4496 ld(-20/2) #17
|
|
1095 e020 jmp y,$20 4497 jmp(Y,'v6502_next') #18
|
|
4498 #nop() #19 Overlap
|
|
4499 #
|
|
4500 label('v6502_JMP1')
|
|
v6502_JMP1: 1096 140d ld $0d,y 4501 ld(hi('v6502_jmp1'),Y) #9,19 JMP $DDDD
|
|
1097 e0c5 jmp y,$c5 4502 jmp(Y,'v6502_jmp1') #10
|
|
4503 #nop() #11 Overlap
|
|
4504 label('v6502_JMP2')
|
|
v6502_JMP2: 1098 140d ld $0d,y 4505 ld(hi('v6502_jmp2'),Y) #9 JMP ($DDDD)
|
|
1099 e0cd jmp y,$cd 4506 jmp(Y,'v6502_jmp2') #10
|
|
4507 #nop() #11 Overlap
|
|
4508 label('v6502_JSR')
|
|
v6502_JSR: 109a 011c ld [$1c] 4509 ld([v6502_S]) #9,11
|
|
109b a002 suba $02 4510 suba(2) #10
|
|
109c d21c st [$1c],x 4511 st([v6502_S],X) #11
|
|
109d 1400 ld $00,y 4512 ld(v6502_Stack>>8,Y) #12
|
|
109e 011b ld [$1b] 4513 ld([v6502_PCH]) #13 Let ADL,ADH point to L operand
|
|
109f c225 st [$25] 4514 st([v6502_ADH]) #14
|
|
10a0 011a ld [$1a] 4515 ld([v6502_PCL]) #15
|
|
10a1 c224 st [$24] 4516 st([v6502_ADL]) #16
|
|
10a2 8001 adda $01 4517 adda(1) #17 Push ++PC
|
|
10a3 c21a st [$1a] 4518 st([v6502_PCL]) #18 Let PCL,PCH point to H operand
|
|
10a4 de00 st [y,x++] 4519 st([Y,Xpp]) #19
|
|
10a5 f0a8 beq $10a8 4520 beq(pc()+3) #20
|
|
10a6 fca9 bra $10a9 4521 bra(pc()+3) #21
|
|
10a7 0000 ld $00 4522 ld(0) #22
|
|
10a8 0001 ld $01 4523 ld(1) #22(!)
|
|
10a9 811b adda [$1b] 4524 adda([v6502_PCH]) #23
|
|
10aa c21b st [$1b] 4525 st([v6502_PCH]) #24
|
|
10ab ce00 st [y,x] 4526 st([Y,X]) #25
|
|
10ac 1124 ld [$24],x 4527 ld([v6502_ADL],X) #26 Fetch L
|
|
10ad 1525 ld [$25],y 4528 ld([v6502_ADH],Y) #27
|
|
10ae 0d00 ld [y,x] 4529 ld([Y,X]) #28
|
|
10af 111a ld [$1a],x 4530 ld([v6502_PCL],X) #29 Fetch H
|
|
10b0 c21a st [$1a] 4531 st([v6502_PCL]) #30
|
|
10b1 151b ld [$1b],y 4532 ld([v6502_PCH],Y) #31
|
|
10b2 0d00 ld [y,x] 4533 ld([Y,X]) #32
|
|
10b3 c21b st [$1b] 4534 st([v6502_PCH]) #33
|
|
10b4 140e ld $0e,y 4535 ld(hi('v6502_next'),Y) #34
|
|
10b5 00ed ld $ed 4536 ld(-38/2) #35
|
|
10b6 e020 jmp y,$20 4537 jmp(Y,'v6502_next') #36
|
|
4538 #nop() #37 Overlap
|
|
4539 #
|
|
4540 label('v6502_INC')
|
|
v6502_INC: 10b7 1411 ld $11,y 4541 ld(hi('v6502_inc'),Y) #9,37
|
|
10b8 e00e jmp y,$0e 4542 jmp(Y,'v6502_inc') #10
|
|
4543 #nop() #11 Overlap
|
|
4544 label('v6502_LDA')
|
|
v6502_LDA: 10b9 1411 ld $11,y 4545 ld(hi('v6502_lda'),Y) #9,11
|
|
10ba e018 jmp y,$18 4546 jmp(Y,'v6502_lda') #10
|
|
4547 #nop() #11 Overlap
|
|
4548 label('v6502_LDX')
|
|
v6502_LDX: 10bb 1411 ld $11,y 4549 ld(hi('v6502_ldx'),Y) #9,11
|
|
10bc e022 jmp y,$22 4550 jmp(Y,'v6502_ldx') #10
|
|
4551 #nop() #11 Overlap
|
|
4552 label('v6502_LDX2')
|
|
v6502_LDX2: 10bd 1411 ld $11,y 4553 ld(hi('v6502_ldx2'),Y) #9,11
|
|
10be e02a jmp y,$2a 4554 jmp(Y,'v6502_ldx2') #10
|
|
4555 #nop() #11 Overlap
|
|
4556 label('v6502_LDY')
|
|
v6502_LDY: 10bf 1411 ld $11,y 4557 ld(hi('v6502_ldy'),Y) #9,11
|
|
10c0 e026 jmp y,$26 4558 jmp(Y,'v6502_ldy') #10
|
|
4559 #nop() #11 Overlap
|
|
4560 label('v6502_STA')
|
|
v6502_STA: 10c1 1411 ld $11,y 4561 ld(hi('v6502_sta'),Y) #9,11
|
|
10c2 e034 jmp y,$34 4562 jmp(Y,'v6502_sta') #10
|
|
4563 #nop() #11 Overlap
|
|
4564 label('v6502_STX')
|
|
v6502_STX: 10c3 1411 ld $11,y 4565 ld(hi('v6502_stx'),Y) #9,11
|
|
10c4 e03a jmp y,$3a 4566 jmp(Y,'v6502_stx') #10
|
|
4567 #nop() #11 Overlap
|
|
4568 label('v6502_STX2')
|
|
v6502_STX2: 10c5 1411 ld $11,y 4569 ld(hi('v6502_stx2'),Y) #9,11
|
|
10c6 e040 jmp y,$40 4570 jmp(Y,'v6502_stx2') #10
|
|
4571 #nop() #11 Overlap
|
|
4572 label('v6502_STY')
|
|
v6502_STY: 10c7 1411 ld $11,y 4573 ld(hi('v6502_sty'),Y) #9,11
|
|
10c8 e048 jmp y,$48 4574 jmp(Y,'v6502_sty') #10
|
|
4575 #nop() #11 Overlap
|
|
4576 label('v6502_TAX')
|
|
v6502_TAX: 10c9 1411 ld $11,y 4577 ld(hi('v6502_tax'),Y) #9,11
|
|
10ca e04d jmp y,$4d 4578 jmp(Y,'v6502_tax') #10
|
|
4579 #nop() #11 Overlap
|
|
4580 label('v6502_TAY')
|
|
v6502_TAY: 10cb 1411 ld $11,y 4581 ld(hi('v6502_tay'),Y) #9,11
|
|
10cc e062 jmp y,$62 4582 jmp(Y,'v6502_tay') #10
|
|
4583 #nop() #11 Overlap
|
|
4584 label('v6502_TXA')
|
|
v6502_TXA: 10cd 1411 ld $11,y 4585 ld(hi('v6502_txa'),Y) #9,11
|
|
10ce e065 jmp y,$65 4586 jmp(Y,'v6502_txa') #10
|
|
4587 #nop() #11 Overlap
|
|
4588 label('v6502_TYA')
|
|
v6502_TYA: 10cf 1411 ld $11,y 4589 ld(hi('v6502_tya'),Y) #9,11
|
|
10d0 e068 jmp y,$68 4590 jmp(Y,'v6502_tya') #10
|
|
4591 #nop() #11 Overlap
|
|
4592 label('v6502_CLV')
|
|
v6502_CLV: 10d1 1411 ld $11,y 4593 ld(hi('v6502_clv'),Y) #9,11
|
|
10d2 e076 jmp y,$76 4594 jmp(Y,'v6502_clv') #10
|
|
4595 #nop() #11 Overlap
|
|
4596 label('v6502_RTI')
|
|
v6502_RTI: 10d3 1411 ld $11,y 4597 ld(hi('v6502_rti'),Y) #9,11
|
|
10d4 e0e4 jmp y,$e4 4598 jmp(Y,'v6502_rti') #10
|
|
4599 #nop() #11 Overlap
|
|
4600 label('v6502_ROR')
|
|
v6502_ROR: 10d5 140d ld $0d,y 4601 ld(hi('v6502_ror'),Y) #9,11
|
|
10d6 e083 jmp y,$83 4602 jmp(Y,'v6502_ror') #10
|
|
4603 #nop() #11 Overlap
|
|
4604 label('v6502_LSR')
|
|
v6502_LSR: 10d7 140d ld $0d,y 4605 ld(hi('v6502_lsr'),Y) #9,11
|
|
10d8 e09d jmp y,$9d 4606 jmp(Y,'v6502_lsr') #10
|
|
4607 #nop() #11 Overlap
|
|
4608 label('v6502_PHA')
|
|
v6502_PHA: 10d9 140d ld $0d,y 4609 ld(hi('v6502_pha'),Y) #9,11
|
|
10da e0e2 jmp y,$e2 4610 jmp(Y,'v6502_pha') #10
|
|
4611 #nop() #11 Overlap
|
|
4612 label('v6502_CLI')
|
|
v6502_CLI: 10db 1411 ld $11,y 4613 ld(hi('v6502_cli'),Y) #9,11
|
|
10dc e06b jmp y,$6b 4614 jmp(Y,'v6502_cli') #10
|
|
4615 #nop() #11 Overlap
|
|
4616 label('v6502_RTS')
|
|
v6502_RTS: 10dd 1411 ld $11,y 4617 ld(hi('v6502_rts'),Y) #9,11
|
|
10de e08f jmp y,$8f 4618 jmp(Y,'v6502_rts') #10
|
|
4619 #nop() #11 Overlap
|
|
4620 label('v6502_PLA')
|
|
v6502_PLA: 10df 140d ld $0d,y 4621 ld(hi('v6502_pla'),Y) #9,11
|
|
10e0 e0d7 jmp y,$d7 4622 jmp(Y,'v6502_pla') #10
|
|
4623 #nop() #11 Overlap
|
|
4624 label('v6502_SEI')
|
|
v6502_SEI: 10e1 1411 ld $11,y 4625 ld(hi('v6502_sei'),Y) #9,11
|
|
10e2 e06e jmp y,$6e 4626 jmp(Y,'v6502_sei') #10
|
|
4627 #nop() #11 Overlap
|
|
4628 label('v6502_TXS')
|
|
v6502_TXS: 10e3 1411 ld $11,y 4629 ld(hi('v6502_txs'),Y) #9,11
|
|
10e4 e05e jmp y,$5e 4630 jmp(Y,'v6502_txs') #10
|
|
4631 #nop() #11 Overlap
|
|
4632 label('v6502_TSX')
|
|
v6502_TSX: 10e5 1411 ld $11,y 4633 ld(hi('v6502_tsx'),Y) #9,11
|
|
10e6 e054 jmp y,$54 4634 jmp(Y,'v6502_tsx') #10
|
|
4635 #nop() #11 Overlap
|
|
4636 label('v6502_CPY')
|
|
v6502_CPY: 10e7 1411 ld $11,y 4637 ld(hi('v6502_cpy'),Y) #9,11
|
|
10e8 e0bd jmp y,$bd 4638 jmp(Y,'v6502_cpy') #10
|
|
4639 #nop() #11 Overlap
|
|
4640 label('v6502_CMP')
|
|
v6502_CMP: 10e9 1411 ld $11,y 4641 ld(hi('v6502_cmp'),Y) #9,11
|
|
10ea e0be jmp y,$be 4642 jmp(Y,'v6502_cmp') #10
|
|
4643 #nop() #11 Overlap
|
|
4644 label('v6502_DEC')
|
|
v6502_DEC: 10eb 1411 ld $11,y 4645 ld(hi('v6502_dec'),Y) #9,11
|
|
10ec e005 jmp y,$05 4646 jmp(Y,'v6502_dec') #10
|
|
4647 #nop() #11 Overlap
|
|
4648 label('v6502_CLD')
|
|
v6502_CLD: 10ed 1411 ld $11,y 4649 ld(hi('v6502_cld'),Y) #9,11
|
|
10ee e071 jmp y,$71 4650 jmp(Y,'v6502_cld') #10
|
|
4651 #nop() #11 Overlap
|
|
4652 label('v6502_CPX')
|
|
v6502_CPX: 10ef 1411 ld $11,y 4653 ld(hi('v6502_cpx'),Y) #9,11
|
|
10f0 e0bb jmp y,$bb 4654 jmp(Y,'v6502_cpx') #10
|
|
4655 #nop() #11 Overlap
|
|
4656 label('v6502_ASL')
|
|
v6502_ASL: 10f1 140d ld $0d,y 4657 ld(hi('v6502_asl'),Y) #9,11
|
|
10f2 e0bf jmp y,$bf 4658 jmp(Y,'v6502_asl') #10
|
|
4659 #nop() #11 Overlap
|
|
4660 label('v6502_PHP')
|
|
v6502_PHP: 10f3 1411 ld $11,y 4661 ld(hi('v6502_php'),Y) #9,11
|
|
10f4 e0a2 jmp y,$a2 4662 jmp(Y,'v6502_php') #10
|
|
4663 #nop() #11 Overlap
|
|
4664 label('v6502_BIT')
|
|
v6502_BIT: 10f5 1411 ld $11,y 4665 ld(hi('v6502_bit'),Y) #9
|
|
10f6 e07d jmp y,$7d 4666 jmp(Y,'v6502_bit') #10
|
|
4667 #nop() #11 Overlap
|
|
4668 label('v6502_ROL')
|
|
v6502_ROL: 10f7 140d ld $0d,y 4669 ld(hi('v6502_rol'),Y) #9
|
|
10f8 e0ac jmp y,$ac 4670 jmp(Y,'v6502_rol') #10
|
|
4671 #nop() #11 Overlap
|
|
4672 label('v6502_PLP')
|
|
v6502_PLP: 10f9 1411 ld $11,y 4673 ld(hi('v6502_plp'),Y) #9
|
|
10fa e0d4 jmp y,$d4 4674 jmp(Y,'v6502_plp') #10
|
|
4675 #nop() #11 Overlap
|
|
4676 label('v6502_SED') # Decimal mode not implemented
|
|
v6502_SED: 10fb 1411 ld $11,y 4677 ld(hi('v6502_sed'),Y) #9,11
|
|
10fc e074 jmp y,$74 4678 jmp(Y,'v6502_sed') #10
|
|
4679 #nop() #11 Overlap
|
|
4680 label('v6502_ILL') # All illegal opcodes map to BRK, except $FF which will crash
|
|
4681 label('v6502_BRK')
|
|
v6502_ILL:
|
|
v6502_BRK: 10fd 140d ld $0d,y 4682 ld(hi('v6502_brk'),Y) #9
|
|
10fe e0ea jmp y,$ea 4683 jmp(Y,'v6502_brk') #10
|
|
4684 #nop() #11 Overlap
|
|
4685
|
|
4686 while pc()&255 < 255:
|
|
4687 nop()
|
|
4688
|
|
4689 # `v6502_RESUME' is the interpreter's secondary entry point for when
|
|
4690 # the opcode and operands were already fetched, just before the last hPulse.
|
|
4691 # It must be at $xxff, prefably somewhere in v6502's own code pages.
|
|
4692 label('v6502_RESUME')
|
|
4693 assert (pc()&255) == 255
|
|
v6502_RESUME: 10ff a006 suba $06 4694 suba(v6502_adjust) #0,11 v6502 secondary entry point
|
|
4695 # --- Page boundary ---
|
|
4696 align(0x100,size=0x200)
|
|
1100 c215 st [$15] 4697 st([vTicks]) #1
|
|
1101 1124 ld [$24],x 4698 ld([v6502_ADL],X) #2
|
|
1102 140f ld $0f,y 4699 ld(hi('v6502_execute'),Y) #3
|
|
1103 e126 jmp y,[$26] 4700 jmp(Y,[v6502_IR]) #4
|
|
1104 fcff bra $ff 4701 bra(255) #5
|
|
4702
|
|
4703 label('v6502_dec')
|
|
v6502_dec: 1105 1525 ld [$25],y 4704 ld([v6502_ADH],Y) #12
|
|
1106 0d00 ld [y,x] 4705 ld([Y,X]) #13
|
|
1107 a001 suba $01 4706 suba(1) #14
|
|
1108 ce00 st [y,x] 4707 st([Y,X]) #15
|
|
1109 c228 st [$28] 4708 st([v6502_Qz]) #16 Z flag
|
|
110a c229 st [$29] 4709 st([v6502_Qn]) #17 N flag
|
|
110b 140e ld $0e,y 4710 ld(hi('v6502_next'),Y) #18
|
|
110c 00f5 ld $f5 4711 ld(-22/2) #19
|
|
110d e020 jmp y,$20 4712 jmp(Y,'v6502_next') #20
|
|
4713 #nop() #21 Overlap
|
|
4714 #
|
|
4715 label('v6502_inc')
|
|
v6502_inc: 110e 1525 ld [$25],y 4716 ld([v6502_ADH],Y) #12,22
|
|
110f 0d00 ld [y,x] 4717 ld([Y,X]) #13
|
|
1110 8001 adda $01 4718 adda(1) #14
|
|
1111 ce00 st [y,x] 4719 st([Y,X]) #15
|
|
1112 c228 st [$28] 4720 st([v6502_Qz]) #16 Z flag
|
|
1113 c229 st [$29] 4721 st([v6502_Qn]) #17 N flag
|
|
1114 140e ld $0e,y 4722 ld(hi('v6502_next'),Y) #18
|
|
1115 00f5 ld $f5 4723 ld(-22/2) #19
|
|
1116 e020 jmp y,$20 4724 jmp(Y,'v6502_next') #20
|
|
1117 0200 nop 4725 nop() #21
|
|
4726
|
|
4727 label('v6502_lda')
|
|
v6502_lda: 1118 0200 nop 4728 nop() #12
|
|
1119 1525 ld [$25],y 4729 ld([v6502_ADH],Y) #13
|
|
111a 0d00 ld [y,x] 4730 ld([Y,X]) #14
|
|
111b c218 st [$18] 4731 st([v6502_A]) #15
|
|
4732 label('.lda16')
|
|
.lda16: 111c c228 st [$28] 4733 st([v6502_Qz]) #16 Z flag
|
|
111d c229 st [$29] 4734 st([v6502_Qn]) #17 N flag
|
|
111e 0200 nop 4735 nop() #18
|
|
111f 140e ld $0e,y 4736 ld(hi('v6502_next'),Y) #19
|
|
1120 e020 jmp y,$20 4737 jmp(Y,'v6502_next') #20
|
|
1121 00f5 ld $f5 4738 ld(-22/2) #21
|
|
4739
|
|
4740 label('v6502_ldx')
|
|
v6502_ldx: 1122 1525 ld [$25],y 4741 ld([v6502_ADH],Y) #12
|
|
1123 0d00 ld [y,x] 4742 ld([Y,X]) #13
|
|
1124 fc1c bra .lda16 4743 bra('.lda16') #14
|
|
1125 c22a st [$2a] 4744 st([v6502_X]) #15
|
|
4745
|
|
4746 label('v6502_ldy')
|
|
v6502_ldy: 1126 1525 ld [$25],y 4747 ld([v6502_ADH],Y) #12
|
|
1127 0d00 ld [y,x] 4748 ld([Y,X]) #13
|
|
1128 fc1c bra .lda16 4749 bra('.lda16') #14
|
|
1129 c22b st [$2b] 4750 st([v6502_Y]) #15
|
|
4751
|
|
4752 label('v6502_ldx2')
|
|
v6502_ldx2: 112a 0124 ld [$24] 4753 ld([v6502_ADL]) #12 Special case $B6: LDX $DD,Y
|
|
112b a12a suba [$2a] 4754 suba([v6502_X]) #13 Undo X offset
|
|
112c 912b adda [$2b],x 4755 adda([v6502_Y],X) #14 Apply Y instead
|
|
112d 0500 ld [x] 4756 ld([X]) #15
|
|
112e c22a st [$2a] 4757 st([v6502_X]) #16
|
|
112f c228 st [$28] 4758 st([v6502_Qz]) #17 Z flag
|
|
1130 c229 st [$29] 4759 st([v6502_Qn]) #18 N flag
|
|
1131 140e ld $0e,y 4760 ld(hi('v6502_next'),Y) #19
|
|
1132 e020 jmp y,$20 4761 jmp(Y,'v6502_next') #20
|
|
1133 00f5 ld $f5 4762 ld(-22/2) #21
|
|
4763
|
|
4764 label('v6502_sta')
|
|
v6502_sta: 1134 1525 ld [$25],y 4765 ld([v6502_ADH],Y) #12
|
|
1135 0118 ld [$18] 4766 ld([v6502_A]) #13
|
|
1136 ce00 st [y,x] 4767 st([Y,X]) #14
|
|
1137 140e ld $0e,y 4768 ld(hi('v6502_next'),Y) #15
|
|
1138 e020 jmp y,$20 4769 jmp(Y,'v6502_next') #16
|
|
1139 00f7 ld $f7 4770 ld(-18/2) #17
|
|
4771
|
|
4772 label('v6502_stx')
|
|
v6502_stx: 113a 1525 ld [$25],y 4773 ld([v6502_ADH],Y) #12
|
|
113b 012a ld [$2a] 4774 ld([v6502_X]) #13
|
|
113c ce00 st [y,x] 4775 st([Y,X]) #14
|
|
113d 140e ld $0e,y 4776 ld(hi('v6502_next'),Y) #15
|
|
113e e020 jmp y,$20 4777 jmp(Y,'v6502_next') #16
|
|
113f 00f7 ld $f7 4778 ld(-18/2) #17
|
|
4779
|
|
4780 label('v6502_stx2')
|
|
v6502_stx2: 1140 0124 ld [$24] 4781 ld([v6502_ADL]) #12 Special case $96: STX $DD,Y
|
|
1141 a12a suba [$2a] 4782 suba([v6502_X]) #13 Undo X offset
|
|
1142 912b adda [$2b],x 4783 adda([v6502_Y],X) #14 Apply Y instead
|
|
1143 012a ld [$2a] 4784 ld([v6502_X]) #15
|
|
1144 c600 st [x] 4785 st([X]) #16
|
|
1145 140e ld $0e,y 4786 ld(hi('v6502_next'),Y) #17
|
|
1146 e020 jmp y,$20 4787 jmp(Y,'v6502_next') #18
|
|
1147 00f6 ld $f6 4788 ld(-20/2) #19
|
|
4789
|
|
4790 label('v6502_sty')
|
|
v6502_sty: 1148 1525 ld [$25],y 4791 ld([v6502_ADH],Y) #12
|
|
1149 012b ld [$2b] 4792 ld([v6502_Y]) #13
|
|
114a ce00 st [y,x] 4793 st([Y,X]) #14
|
|
114b 140e ld $0e,y 4794 ld(hi('v6502_next'),Y) #15
|
|
114c e020 jmp y,$20 4795 jmp(Y,'v6502_next') #16
|
|
4796 label('v6502_tax')
|
|
v6502_tax: 114d 00f7 ld $f7 4797 ld(-18/2) #17,12
|
|
4798 #
|
|
4799 #label('v6502_tax')
|
|
4800 #nop() #12 Overlap
|
|
114e 0118 ld [$18] 4801 ld([v6502_A]) #13
|
|
114f c22a st [$2a] 4802 st([v6502_X]) #14
|
|
4803 label('.tax15')
|
|
.tax15: 1150 c228 st [$28] 4804 st([v6502_Qz]) #15 Z flag
|
|
1151 c229 st [$29] 4805 st([v6502_Qn]) #16 N flag
|
|
1152 140e ld $0e,y 4806 ld(hi('v6502_next'),Y) #17
|
|
1153 e020 jmp y,$20 4807 jmp(Y,'v6502_next') #18
|
|
4808 label('v6502_tsx')
|
|
v6502_tsx: 1154 00f6 ld $f6 4809 ld(-20/2) #19
|
|
4810 #
|
|
4811 #label('v6502_tsx')
|
|
4812 #nop() #12 Overlap
|
|
1155 011c ld [$1c] 4813 ld([v6502_S]) #13
|
|
1156 a001 suba $01 4814 suba(1) #14 Shift down on export
|
|
1157 c22a st [$2a] 4815 st([v6502_X]) #15
|
|
4816 label('.tsx16')
|
|
.tsx16: 1158 c228 st [$28] 4817 st([v6502_Qz]) #16 Z flag
|
|
1159 c229 st [$29] 4818 st([v6502_Qn]) #17 N flag
|
|
115a 0200 nop 4819 nop() #18
|
|
115b 140e ld $0e,y 4820 ld(hi('v6502_next'),Y) #19
|
|
115c e020 jmp y,$20 4821 jmp(Y,'v6502_next') #20
|
|
115d 00f5 ld $f5 4822 ld(-22/2) #21
|
|
4823
|
|
4824 label('v6502_txs')
|
|
v6502_txs: 115e 012a ld [$2a] 4825 ld([v6502_X]) #12
|
|
115f 8001 adda $01 4826 adda(1) #13 Shift up on import
|
|
1160 fc58 bra .tsx16 4827 bra('.tsx16') #14
|
|
1161 c21c st [$1c] 4828 st([v6502_S]) #15
|
|
4829
|
|
4830 label('v6502_tay')
|
|
v6502_tay: 1162 0118 ld [$18] 4831 ld([v6502_A]) #12
|
|
1163 fc50 bra .tax15 4832 bra('.tax15') #13
|
|
1164 c22b st [$2b] 4833 st([v6502_Y]) #14
|
|
4834
|
|
4835 label('v6502_txa')
|
|
v6502_txa: 1165 012a ld [$2a] 4836 ld([v6502_X]) #12
|
|
1166 fc50 bra .tax15 4837 bra('.tax15') #13
|
|
1167 c218 st [$18] 4838 st([v6502_A]) #14
|
|
4839
|
|
4840 label('v6502_tya')
|
|
v6502_tya: 1168 012b ld [$2b] 4841 ld([v6502_Y]) #12
|
|
1169 fc50 bra .tax15 4842 bra('.tax15') #13
|
|
116a c218 st [$18] 4843 st([v6502_A]) #14
|
|
4844
|
|
4845 label('v6502_cli')
|
|
v6502_cli: 116b 0127 ld [$27] 4846 ld([v6502_P]) #12
|
|
116c fc79 bra .clv15 4847 bra('.clv15') #13
|
|
116d 20fb anda $fb 4848 anda(~v6502_Iflag) #14
|
|
4849
|
|
4850 label('v6502_sei')
|
|
v6502_sei: 116e 0127 ld [$27] 4851 ld([v6502_P]) #12
|
|
116f fc79 bra .clv15 4852 bra('.clv15') #13
|
|
1170 4004 ora $04 4853 ora(v6502_Iflag) #14
|
|
4854
|
|
4855 label('v6502_cld')
|
|
v6502_cld: 1171 0127 ld [$27] 4856 ld([v6502_P]) #12
|
|
1172 fc79 bra .clv15 4857 bra('.clv15') #13
|
|
1173 20f7 anda $f7 4858 anda(~v6502_Dflag) #14
|
|
4859
|
|
4860 label('v6502_sed')
|
|
v6502_sed: 1174 0127 ld [$27] 4861 ld([v6502_P]) #12
|
|
1175 fc79 bra .clv15 4862 bra('.clv15') #13
|
|
4863 label('v6502_clv')
|
|
v6502_clv: 1176 4008 ora $08 4864 ora(v6502_Dflag) #14,12 Overlap
|
|
4865 #
|
|
4866 #label('v6502_clv')
|
|
4867 #nop() #12
|
|
1177 0127 ld [$27] 4868 ld([v6502_P]) #13
|
|
1178 207f anda $7f 4869 anda(~v6502_Vemu) #14
|
|
4870 label('.clv15')
|
|
.clv15: 1179 c227 st [$27] 4871 st([v6502_P]) #15
|
|
117a 140e ld $0e,y 4872 ld(hi('v6502_next'),Y) #16
|
|
117b 00f6 ld $f6 4873 ld(-20/2) #17
|
|
117c e020 jmp y,$20 4874 jmp(Y,'v6502_next') #18
|
|
4875 label('v6502_bit')
|
|
v6502_bit: 117d 0200 nop 4876 nop() #19,12
|
|
4877 #
|
|
4878 #label('v6502_bit')
|
|
4879 #nop() #12 Overlap
|
|
117e 1124 ld [$24],x 4880 ld([v6502_ADL],X) #13
|
|
117f 1525 ld [$25],y 4881 ld([v6502_ADH],Y) #14
|
|
1180 0d00 ld [y,x] 4882 ld([Y,X]) #15
|
|
1181 c229 st [$29] 4883 st([v6502_Qn]) #16 N flag
|
|
1182 2118 anda [$18] 4884 anda([v6502_A]) #17 This is a reason we keep N and Z in separate bytes
|
|
1183 c228 st [$28] 4885 st([v6502_Qz]) #18 Z flag
|
|
1184 0127 ld [$27] 4886 ld([v6502_P]) #19
|
|
1185 207f anda $7f 4887 anda(~v6502_Vemu) #20
|
|
1186 c227 st [$27] 4888 st([v6502_P]) #21
|
|
1187 0d00 ld [y,x] 4889 ld([Y,X]) #22
|
|
1188 8200 adda ac 4890 adda(AC) #23
|
|
1189 2080 anda $80 4891 anda(v6502_Vemu) #24
|
|
118a 4127 ora [$27] 4892 ora([v6502_P]) #25
|
|
118b c227 st [$27] 4893 st([v6502_P]) #26 Update V
|
|
118c 140e ld $0e,y 4894 ld(hi('v6502_next'),Y) #27
|
|
118d e020 jmp y,$20 4895 jmp(Y,'v6502_next') #28
|
|
118e 00f1 ld $f1 4896 ld(-30/2) #29
|
|
4897
|
|
4898 label('v6502_rts')
|
|
v6502_rts: 118f 011c ld [$1c] 4899 ld([v6502_S]) #12
|
|
1190 1200 ld ac,x 4900 ld(AC,X) #13
|
|
1191 8002 adda $02 4901 adda(2) #14
|
|
1192 c21c st [$1c] 4902 st([v6502_S]) #15
|
|
1193 1400 ld $00,y 4903 ld(0,Y) #16
|
|
1194 0d00 ld [y,x] 4904 ld([Y,X]) #17
|
|
1195 de00 st [y,x++] 4905 st([Y,Xpp]) #18 Just X++
|
|
1196 8001 adda $01 4906 adda(1) #19
|
|
1197 c21a st [$1a] 4907 st([v6502_PCL]) #20
|
|
1198 f09b beq $119b 4908 beq(pc()+3) #21
|
|
1199 fc9c bra $119c 4909 bra(pc()+3) #22
|
|
119a 0000 ld $00 4910 ld(0) #23
|
|
119b 0001 ld $01 4911 ld(1) #23(!)
|
|
119c 8d00 adda [y,x] 4912 adda([Y,X]) #24
|
|
119d c21b st [$1b] 4913 st([v6502_PCH]) #25
|
|
119e 0200 nop 4914 nop() #26
|
|
119f 140e ld $0e,y 4915 ld(hi('v6502_next'),Y) #27
|
|
11a0 e020 jmp y,$20 4916 jmp(Y,'v6502_next') #28
|
|
11a1 00f1 ld $f1 4917 ld(-30/2) #29
|
|
4918
|
|
4919 label('v6502_php')
|
|
v6502_php: 11a2 011c ld [$1c] 4920 ld([v6502_S]) #12
|
|
11a3 a001 suba $01 4921 suba(1) #13
|
|
11a4 d21c st [$1c],x 4922 st([v6502_S],X) #14
|
|
11a5 0127 ld [$27] 4923 ld([v6502_P]) #15
|
|
11a6 20bd anda $bd 4924 anda(~v6502_Vflag&~v6502_Zflag) #16 Keep Vemu,B,D,I,C
|
|
11a7 f4aa bge $11aa 4925 bpl(pc()+3) #17 V to bit 6 and clear N
|
|
11a8 fcaa bra $11aa 4926 bra(pc()+2) #18
|
|
11a9 60c0 xora $c0 4927 xora(v6502_Vflag^v6502_Vemu) #19
|
|
11aa c600 st [x] 4928 st([X]) #19,20
|
|
11ab 0128 ld [$28] 4929 ld([v6502_Qz]) #21 Z flag
|
|
11ac f0af beq $11af 4930 beq(pc()+3) #22
|
|
11ad fcb0 bra $11b0 4931 bra(pc()+3) #23
|
|
11ae 0000 ld $00 4932 ld(0) #24
|
|
11af 0002 ld $02 4933 ld(v6502_Zflag) #24(!)
|
|
11b0 4500 ora [x] 4934 ora([X]) #25
|
|
11b1 c600 st [x] 4935 st([X]) #26
|
|
11b2 0129 ld [$29] 4936 ld([v6502_Qn]) #27 N flag
|
|
11b3 2080 anda $80 4937 anda(0x80) #28
|
|
11b4 4500 ora [x] 4938 ora([X]) #29
|
|
11b5 4020 ora $20 4939 ora(v6502_Uflag) #30 Unused bit
|
|
11b6 c600 st [x] 4940 st([X]) #31
|
|
11b7 0200 nop 4941 nop() #32
|
|
11b8 140e ld $0e,y 4942 ld(hi('v6502_next'),Y) #33
|
|
11b9 e020 jmp y,$20 4943 jmp(Y,'v6502_next') #34
|
|
11ba 00ee ld $ee 4944 ld(-36/2) #35
|
|
4945
|
|
4946 label('v6502_cpx')
|
|
v6502_cpx: 11bb fcc0 bra .cmp14 4947 bra('.cmp14') #12
|
|
11bc 012a ld [$2a] 4948 ld([v6502_X]) #13
|
|
4949
|
|
4950 label('v6502_cpy')
|
|
v6502_cpy: 11bd fcc0 bra .cmp14 4951 bra('.cmp14') #12
|
|
4952 label('v6502_cmp')
|
|
v6502_cmp: 11be 012b ld [$2b] 4953 ld([v6502_Y]) #13,12
|
|
4954 #
|
|
4955 #label('v6502_cmp') #12 Overlap
|
|
4956 assert v6502_Cflag == 1
|
|
11bf 0118 ld [$18] 4957 ld([v6502_A]) #13
|
|
4958 label('.cmp14')
|
|
.cmp14: 11c0 1525 ld [$25],y 4959 ld([v6502_ADH],Y) #14
|
|
11c1 e8c7 blt .cmp17 4960 bmi('.cmp17') #15 Carry?
|
|
11c2 ad00 suba [y,x] 4961 suba([Y,X]) #16
|
|
11c3 c228 st [$28] 4962 st([v6502_Qz]) #17 Z flag
|
|
11c4 c229 st [$29] 4963 st([v6502_Qn]) #18 N flag
|
|
11c5 fccb bra .cmp21 4964 bra('.cmp21') #19
|
|
11c6 4d00 ora [y,x] 4965 ora([Y,X]) #20
|
|
4966 label('.cmp17')
|
|
.cmp17: 11c7 c228 st [$28] 4967 st([v6502_Qz]) #17 Z flag
|
|
11c8 c229 st [$29] 4968 st([v6502_Qn]) #18 N flag
|
|
11c9 2d00 anda [y,x] 4969 anda([Y,X]) #19
|
|
11ca 0200 nop 4970 nop() #20
|
|
4971 label('.cmp21')
|
|
.cmp21: 11cb 6080 xora $80 4972 xora(0x80) #21
|
|
11cc 3080 anda $80,x 4973 anda(0x80,X) #22 Move carry to bit 0
|
|
11cd 0127 ld [$27] 4974 ld([v6502_P]) #23 C flag
|
|
11ce 20fe anda $fe 4975 anda(~1) #24
|
|
11cf 4500 ora [x] 4976 ora([X]) #25
|
|
11d0 c227 st [$27] 4977 st([v6502_P]) #26
|
|
11d1 140e ld $0e,y 4978 ld(hi('v6502_next'),Y) #27
|
|
11d2 e020 jmp y,$20 4979 jmp(Y,'v6502_next') #28
|
|
11d3 00f1 ld $f1 4980 ld(-30/2) #29
|
|
4981
|
|
4982 label('v6502_plp')
|
|
4983 assert v6502_Nflag == 128
|
|
4984 assert 2*v6502_Vflag == v6502_Vemu
|
|
v6502_plp: 11d4 011c ld [$1c] 4985 ld([v6502_S]) #12
|
|
11d5 1200 ld ac,x 4986 ld(AC,X) #13
|
|
11d6 8001 adda $01 4987 adda(1) #14
|
|
11d7 c21c st [$1c] 4988 st([v6502_S]) #15
|
|
11d8 0500 ld [x] 4989 ld([X]) #16
|
|
11d9 c229 st [$29] 4990 st([v6502_Qn]) #17 N flag
|
|
11da 2002 anda $02 4991 anda(v6502_Zflag) #18
|
|
11db 6002 xora $02 4992 xora(v6502_Zflag) #19
|
|
11dc c228 st [$28] 4993 st([v6502_Qz]) #20 Z flag
|
|
11dd 0500 ld [x] 4994 ld([X]) #21
|
|
11de 207f anda $7f 4995 anda(~v6502_Vemu) #22 V to bit 7
|
|
11df 8040 adda $40 4996 adda(v6502_Vflag) #23
|
|
11e0 c227 st [$27] 4997 st([v6502_P]) #24 All other flags
|
|
11e1 140e ld $0e,y 4998 ld(hi('v6502_next'),Y) #25
|
|
11e2 e020 jmp y,$20 4999 jmp(Y,'v6502_next') #26
|
|
11e3 00f2 ld $f2 5000 ld(-28/2) #27
|
|
5001
|
|
5002 label('v6502_rti')
|
|
v6502_rti: 11e4 011c ld [$1c] 5003 ld([v6502_S]) #12
|
|
11e5 1200 ld ac,x 5004 ld(AC,X) #13
|
|
11e6 8003 adda $03 5005 adda(3) #14
|
|
11e7 c21c st [$1c] 5006 st([v6502_S]) #15
|
|
11e8 0500 ld [x] 5007 ld([X]) #16
|
|
11e9 c229 st [$29] 5008 st([v6502_Qn]) #17 N flag
|
|
11ea 2002 anda $02 5009 anda(v6502_Zflag) #18
|
|
11eb 6002 xora $02 5010 xora(v6502_Zflag) #19
|
|
11ec c228 st [$28] 5011 st([v6502_Qz]) #20 Z flag
|
|
11ed 1400 ld $00,y 5012 ld(0,Y) #21
|
|
11ee 0d00 ld [y,x] 5013 ld([Y,X]) #22
|
|
11ef de00 st [y,x++] 5014 st([Y,Xpp]) #23 Just X++
|
|
11f0 207f anda $7f 5015 anda(~v6502_Vemu) #24 V to bit 7
|
|
11f1 8040 adda $40 5016 adda(v6502_Vflag) #25
|
|
11f2 c227 st [$27] 5017 st([v6502_P]) #26 All other flags
|
|
11f3 0d00 ld [y,x] 5018 ld([Y,X]) #27
|
|
11f4 de00 st [y,x++] 5019 st([Y,Xpp]) #28 Just X++
|
|
11f5 c21a st [$1a] 5020 st([v6502_PCL]) #29
|
|
11f6 0d00 ld [y,x] 5021 ld([Y,X]) #30
|
|
11f7 c21b st [$1b] 5022 st([v6502_PCH]) #31
|
|
11f8 0200 nop 5023 nop() #32
|
|
11f9 140e ld $0e,y 5024 ld(hi('v6502_next'),Y) #33
|
|
11fa e020 jmp y,$20 5025 jmp(Y,'v6502_next') #34
|
|
11fb 00ee ld $ee 5026 ld(-36/2) #35
|
|
5027
|
|
5028 #-----------------------------------------------------------------------
|
|
5029 # Extended vertical blank logic: interrupts
|
|
5030 #-----------------------------------------------------------------------
|
|
11fc 0200 nop 5031 align(0x100)
|
|
11fd 0200 nop
|
|
11fe 0200 nop
|
|
11ff 0200 nop
|
|
5032
|
|
5033 # Check if an IRQ handler is defined
|
|
5034 label('vBlankFirst#78')
|
|
vBlankFirst#78:
|
|
1200 09f6 ld [y,$f6] 5035 ld([Y,vIRQ_v5]) #78
|
|
1201 49f7 ora [y,$f7] 5036 ora([Y,vIRQ_v5+1]) #79
|
|
5037 bne('vBlankFirst#82') #80
|
|
1202 ec09 bne vBlankFirst#82
|
|
1203 0116 ld [$16] 5038 ld([vPC]) #81
|
|
1204 0055 ld $55 5039 runVcpu(186-82-extra, #82 Application cycles (scan line 0)
|
|
1205 c21e st [$1e]
|
|
1206 1505 ld [$05],y
|
|
1207 e0ff jmp y,$ff
|
|
1208 001f ld $1f
|
|
5040 '---D line 0 timeout but no irq',
|
|
5041 returnTo='vBlankFirst#186')
|
|
5042
|
|
5043 label('vBlankFirst#82')
|
|
vBlankFirst#82:
|
|
1209 c230 st [$30] 5044 st([0x30]) #82 Save vPC
|
|
120a 0117 ld [$17] 5045 ld([vPC+1]) #83
|
|
120b c231 st [$31] 5046 st([0x31]) #84
|
|
120c 0118 ld [$18] 5047 ld([vAC]) #85 Save vAC
|
|
120d c232 st [$32] 5048 st([0x32]) #86
|
|
120e 0119 ld [$19] 5049 ld([vAC+1]) #87
|
|
120f c233 st [$33] 5050 st([0x33]) #88
|
|
1210 09f6 ld [y,$f6] 5051 ld([Y,vIRQ_v5]) #89 Set vPC to vIRQ
|
|
1211 a002 suba $02 5052 suba(2) #90
|
|
1212 c216 st [$16] 5053 st([vPC]) #91
|
|
1213 09f7 ld [y,$f7] 5054 ld([Y,vIRQ_v5+1]) #92
|
|
1214 c217 st [$17] 5055 st([vPC+1]) #93
|
|
1215 0105 ld [$05] 5056 ld([vCpuSelect]) #94 Handler must save this if needed
|
|
1216 c219 st [$19] 5057 st([vAC+1]) #95
|
|
1217 0000 ld $00 5058 ld(0) #96
|
|
1218 c218 st [$18] 5059 st([vAC]) #97
|
|
1219 0002 ld $02 5060 ld(hi('ENTER')) #98 Set vCpuSelect to ENTER (=regular vCPU)
|
|
121a c205 st [$05] 5061 st([vCpuSelect]) #99
|
|
121b 0055 ld $55 5062 runVcpu(186-100-extra, #100 Application cycles (scan line 0)
|
|
121c c21e st [$1e]
|
|
121d 1505 ld [$05],y
|
|
121e e0ff jmp y,$ff
|
|
121f 0016 ld $16
|
|
5063 '---D line 0 timeout with irq',
|
|
5064 returnTo='vBlankFirst#186')
|
|
5065
|
|
5066 # vIRQ sequence WITH interpreter switch
|
|
5067 label('vRTI#18')
|
|
vRTI#18: 1220 0500 ld [x] 5068 ld([X]) #18
|
|
1221 c205 st [$05] 5069 st([vCpuSelect]) #19
|
|
1222 0130 ld [$30] 5070 ld([0x30]) #20
|
|
1223 c216 st [$16] 5071 st([vPC]) #21
|
|
1224 0131 ld [$31] 5072 ld([0x31]) #22
|
|
1225 c217 st [$17] 5073 st([vPC+1]) #23
|
|
1226 0132 ld [$32] 5074 ld([0x32]) #24
|
|
1227 c218 st [$18] 5075 st([vAC]) #25
|
|
1228 0133 ld [$33] 5076 ld([0x33]) #26
|
|
1229 c219 st [$19] 5077 st([vAC+1]) #27
|
|
122a 0200 nop 5078 nop() #0
|
|
122b 1403 ld $03,y 5079 ld(hi('RESYNC'),Y) #1
|
|
122c e00c jmp y,$0c 5080 jmp(Y,'RESYNC') #2
|
|
122d 0115 ld [$15] 5081 ld([vTicks]) #3
|
|
5082
|
|
5083 # Entered last line of vertical blank (line 40)
|
|
5084 label('vBlankLast#34')
|
|
5085
|
|
5086 #-----------------------------------------------------------------------
|
|
5087 # Extended vertical blank logic: game controller decoding
|
|
5088 #-----------------------------------------------------------------------
|
|
5089
|
|
5090 # Game controller types
|
|
5091 # TypeA: Based on 74LS165 shift register (not supported)
|
|
5092 # TypeB: Based on CD4021B shift register (standard)
|
|
5093 # TypeC: Based on priority encoder
|
|
5094 #
|
|
5095 # Notes:
|
|
5096 # - TypeA was only used during development and first beta test, before ROM v1
|
|
5097 # - TypeB appears as type A with negative logic levels
|
|
5098 # - TypeB is the game controller type that comes with the original kit and ROM v1
|
|
5099 # - TypeB is mimicked by BabelFish / Pluggy McPlugface
|
|
5100 # - TypeB requires a prolonged /SER_LATCH, therefore vPulse is 8 scanlines, not 2
|
|
5101 # - TypeB and TypeC can be sampled in the same scanline
|
|
5102 # - TypeA is 1 scanline shifted as it looks at a different edge (XXX up or down?)
|
|
5103 # - TypeC gives incomplete information: lower buttons overshadow higher ones
|
|
5104 #
|
|
5105 # TypeC Alias Button TypeB
|
|
5106 # 00000000 ^@ -> Right 11111110
|
|
5107 # 00000001 ^A -> Left 11111101
|
|
5108 # 00000011 ^C -> Down 11111011
|
|
5109 # 00000111 ^G -> Up 11110111
|
|
5110 # 00001111 ^O -> Start 11101111
|
|
5111 # 00011111 ^_ -> Select 11011111
|
|
5112 # 00111111 ? -> B 10111111
|
|
5113 # 01111111 DEL -> A 01111111
|
|
5114 # 11111111 -> (None) 11111111
|
|
5115 #
|
|
5116 # Conversion formula:
|
|
5117 # f(x) := 254 - x
|
|
5118
|
|
5119 # Detect controller TypeC codes
|
|
vBlankLast#34:
|
|
122e 010f ld [$0f] 5120 ld([serialRaw]) #34 if serialRaw in [0,1,3,7,15,31,63,127,255]
|
|
122f 8001 adda $01 5121 adda(1) #35
|
|
1230 210f anda [$0f] 5122 anda([serialRaw]) #36
|
|
1231 ec42 bne .buttons#39 5123 bne('.buttons#39') #37
|
|
5124
|
|
5125 # TypeC
|
|
1232 010f ld [$0f] 5126 ld([serialRaw]) #38 [TypeC] if serialRaw < serialLast
|
|
1233 8001 adda $01 5127 adda(1) #39
|
|
1234 2110 anda [$10] 5128 anda([serialLast]) #40
|
|
1235 ec39 bne .buttons#43 5129 bne('.buttons#43') #41
|
|
1236 00fe ld $fe 5130 ld(254) #42 then clear the selected bit
|
|
1237 0200 nop 5131 nop() #43
|
|
1238 fc3c bra .buttons#46 5132 bra('.buttons#46') #44
|
|
5133 label('.buttons#43')
|
|
.buttons#43: 1239 a10f suba [$0f] 5134 suba([serialRaw]) #43,45
|
|
123a 2111 anda [$11] 5135 anda([buttonState]) #44
|
|
123b c211 st [$11] 5136 st([buttonState]) #45
|
|
5137 label('.buttons#46')
|
|
.buttons#46: 123c 010f ld [$0f] 5138 ld([serialRaw]) #46 Set the lower bits
|
|
123d 4111 ora [$11] 5139 ora([buttonState]) #47
|
|
5140 label('.buttons#48')
|
|
.buttons#48: 123e c211 st [$11] 5141 st([buttonState]) #48
|
|
123f 010f ld [$0f] 5142 ld([serialRaw]) #49 Update serialLast for next pass
|
|
1240 e0b3 jmp y,$b3 5143 jmp(Y,'vBlankLast#52') #50
|
|
1241 c210 st [$10] 5144 st([serialLast]) #51
|
|
5145
|
|
5146 # TypeB
|
|
5147 # pChange = pNew & ~pOld
|
|
5148 # nChange = nNew | ~nOld {DeMorgan}
|
|
5149 label('.buttons#39')
|
|
.buttons#39: 1242 00ff ld $ff 5150 ld(255) #39 [TypeB] Bitwise edge-filter to detect button presses
|
|
1243 6110 xora [$10] 5151 xora([serialLast]) #40
|
|
1244 410f ora [$0f] 5152 ora([serialRaw]) #41 Catch button-press events
|
|
1245 2111 anda [$11] 5153 anda([buttonState]) #42 Keep active button presses
|
|
1246 410f ora [$0f] 5154 ora([serialRaw]) #43
|
|
1247 0200 nop 5155 nop() #44
|
|
1248 0200 nop 5156 nop() #45
|
|
1249 fc3e bra .buttons#48 5157 bra('.buttons#48') #46
|
|
124a 0200 nop 5158 nop() #47
|
|
5159
|
|
5160
|
|
5161 #-----------------------------------------------------------------------
|
|
5162 # More SYS functions
|
|
5163 #-----------------------------------------------------------------------
|
|
5164
|
|
5165 # SYS_Exec_88 implementation
|
|
5166 label('sys_Exec')
|
|
sys_Exec: 124b d617 st [$17],y 5167 st([vPC+1],Y) #18 Clear vPCH and Y
|
|
124c 011c ld [$1c] 5168 ld([vSP]) #19 Place ROM loader below current stack pointer
|
|
124d a037 suba $37 5169 suba(53+2) #20 (AC -> *+0) One extra word for PUSH
|
|
124e d21d st [$1d],x 5170 st([vTmp],X) #21
|
|
124f 80fe adda $fe 5171 adda(-2) #22 (AC -> *-2)
|
|
1250 c216 st [$16] 5172 st([vPC]) #23
|
|
5173 # Start of manually compiled vCPU section
|
|
1251 dc75 st $75,[y,x++] 5174 st('PUSH', [Y,Xpp]) #24 *+0
|
|
1252 dccf st $cf,[y,x++] 5175 st('CALL', [Y,Xpp]) #25 *+26 Fetch first byte
|
|
1253 8023 adda $23 5176 adda(33-(-2)) #26 (AC -> *+33)
|
|
1254 de00 st [y,x++] 5177 st( [Y,Xpp]) #27 *+27
|
|
1255 dc5e st $5e,[y,x++] 5178 st('ST', [Y,Xpp]) #28 *+3 Chunk copy loop
|
|
1256 dc27 st $27,[y,x++] 5179 st(sysArgs+3, [Y,Xpp]) #29 *+4 High-address comes first
|
|
1257 dccf st $cf,[y,x++] 5180 st('CALL', [Y,Xpp]) #30 *+5
|
|
1258 de00 st [y,x++] 5181 st( [Y,Xpp]) #31 *+6
|
|
1259 dc5e st $5e,[y,x++] 5182 st('ST', [Y,Xpp]) #32 *+7
|
|
125a dc26 st $26,[y,x++] 5183 st(sysArgs+2, [Y,Xpp]) #33 *+8 Then the low address
|
|
125b dccf st $cf,[y,x++] 5184 st('CALL', [Y,Xpp]) #34 *+9
|
|
125c de00 st [y,x++] 5185 st( [Y,Xpp]) #35 *+10
|
|
125d dc5e st $5e,[y,x++] 5186 st('ST', [Y,Xpp]) #36 *+11 Byte copy loop
|
|
125e dc28 st $28,[y,x++] 5187 st(sysArgs+4, [Y,Xpp]) #37 *+12 Byte count (0 means 256)
|
|
125f dccf st $cf,[y,x++] 5188 st('CALL', [Y,Xpp]) #38 *+13
|
|
1260 de00 st [y,x++] 5189 st( [Y,Xpp]) #39 *+14
|
|
1261 dcf0 st $f0,[y,x++] 5190 st('POKE', [Y,Xpp]) #40 *+15
|
|
1262 dc26 st $26,[y,x++] 5191 st(sysArgs+2, [Y,Xpp]) #41 *+16
|
|
1263 dc93 st $93,[y,x++] 5192 st('INC', [Y,Xpp]) #42 *+17
|
|
1264 dc26 st $26,[y,x++] 5193 st(sysArgs+2, [Y,Xpp]) #43 *+18
|
|
1265 dc1a st $1a,[y,x++] 5194 st('LD', [Y,Xpp]) #44 *+19
|
|
1266 dc28 st $28,[y,x++] 5195 st(sysArgs+4, [Y,Xpp]) #45 *+20
|
|
1267 dce6 st $e6,[y,x++] 5196 st('SUBI', [Y,Xpp]) #46 *+21
|
|
1268 dc01 st $01,[y,x++] 5197 st(1, [Y,Xpp]) #47 *+22
|
|
1269 dc35 st $35,[y,x++] 5198 st('BCC', [Y,Xpp]) #48 *+23
|
|
126a dc72 st $72,[y,x++] 5199 st('NE', [Y,Xpp]) #49 *+24
|
|
126b 80e8 adda $e8 5200 adda(11-2-33) #50 (AC -> *+9)
|
|
126c de00 st [y,x++] 5201 st( [Y,Xpp]) #51 *+25
|
|
126d dccf st $cf,[y,x++] 5202 st('CALL', [Y,Xpp]) #52 *+26 Go to next block
|
|
126e 8018 adda $18 5203 adda(33-9) #53 (AC -> *+33)
|
|
126f de00 st [y,x++] 5204 st( [Y,Xpp]) #54 *+27
|
|
1270 dc35 st $35,[y,x++] 5205 st('BCC', [Y,Xpp]) #55 *+28
|
|
1271 dc72 st $72,[y,x++] 5206 st('NE', [Y,Xpp]) #56 *+29
|
|
1272 80e0 adda $e0 5207 adda(3-2-33) #57 (AC -> *+1)
|
|
1273 de00 st [y,x++] 5208 st( [Y,Xpp]) #58 *+30
|
|
1274 dc63 st $63,[y,x++] 5209 st('POP', [Y,Xpp]) #59 *+31 End
|
|
1275 dcff st $ff,[y,x++] 5210 st('RET', [Y,Xpp]) #60 *+32
|
|
5211 # Pointer constant pointing to the routine below (for use by CALL)
|
|
1276 8022 adda $22 5212 adda(35-1) #61 (AC -> *+35)
|
|
1277 de00 st [y,x++] 5213 st( [Y,Xpp]) #62 *+33
|
|
1278 dc00 st $00,[y,x++] 5214 st(0, [Y,Xpp]) #63 *+34
|
|
5215 # Routine to read next byte from ROM and advance read pointer
|
|
1279 dc1a st $1a,[y,x++] 5216 st('LD', [Y,Xpp]) #64 *+35 Test for end of ROM table
|
|
127a dc24 st $24,[y,x++] 5217 st(sysArgs+0, [Y,Xpp]) #65 *+36
|
|
127b dc8c st $8c,[y,x++] 5218 st('XORI', [Y,Xpp]) #66 *+37
|
|
127c dcfb st $fb,[y,x++] 5219 st(251, [Y,Xpp]) #67 *+38
|
|
127d dc35 st $35,[y,x++] 5220 st('BCC', [Y,Xpp]) #68 *+39
|
|
127e dc72 st $72,[y,x++] 5221 st('NE', [Y,Xpp]) #69 *+40
|
|
127f 8009 adda $09 5222 adda(46-2-35) #70 (AC -> *+44)
|
|
1280 de00 st [y,x++] 5223 st( [Y,Xpp]) #71 *+41
|
|
1281 dc5e st $5e,[y,x++] 5224 st('ST', [Y,Xpp]) #72 *+42 Wrap to next ROM page
|
|
1282 dc24 st $24,[y,x++] 5225 st(sysArgs+0, [Y,Xpp]) #73 *+43
|
|
1283 dc93 st $93,[y,x++] 5226 st('INC', [Y,Xpp]) #74 *+44
|
|
1284 dc25 st $25,[y,x++] 5227 st(sysArgs+1, [Y,Xpp]) #75 *+45
|
|
1285 dc21 st $21,[y,x++] 5228 st('LDW', [Y,Xpp]) #76 *+46 Read next byte from ROM table
|
|
1286 dc24 st $24,[y,x++] 5229 st(sysArgs+0, [Y,Xpp]) #77 *+47
|
|
1287 dc7f st $7f,[y,x++] 5230 st('LUP', [Y,Xpp]) #78 *+48
|
|
1288 dc00 st $00,[y,x++] 5231 st(0, [Y,Xpp]) #79 *+49
|
|
1289 dc93 st $93,[y,x++] 5232 st('INC', [Y,Xpp]) #80 *+50 Increment read pointer
|
|
128a dc24 st $24,[y,x++] 5233 st(sysArgs+0, [Y,Xpp]) #81 *+51
|
|
128b dcff st $ff,[y,x++] 5234 st('RET', [Y,Xpp]) #82 *+52 Return
|
|
5235 # Return to interpreter
|
|
128c 1403 ld $03,y 5236 ld(hi('REENTER'),Y) #83
|
|
128d e0cb jmp y,$cb 5237 jmp(Y,'REENTER') #84
|
|
128e 00d4 ld $d4 5238 ld(-88/2) #85
|
|
5239
|
|
5240 # SYS_VDrawBits_134 implementation
|
|
5241 label('sys_VDrawBits')
|
|
sys_VDrawBits:
|
|
128f 0000 ld $00 5242 ld(0) #18
|
|
5243 label('.sysVdb0')
|
|
.sysVdb0: 1290 c21d st [$1d] 5244 st([vTmp]) #19+i*25
|
|
1291 9529 adda [$29],y 5245 adda([sysArgs+5],Y) #20+i*25 Y=[sysPos+1]+[vTmp]
|
|
1292 0126 ld [$26] 5246 ld([sysArgs+2]) #21+i*25 Select color
|
|
1293 e896 blt $1296 5247 bmi(pc()+3) #22+i*25
|
|
1294 fc97 bra $1297 5248 bra(pc()+3) #23+i*25
|
|
1295 0124 ld [$24] 5249 ld([sysArgs+0]) #24+i*25
|
|
1296 0125 ld [$25] 5250 ld([sysArgs+1]) #24+i*25(!)
|
|
1297 ce00 st [y,x] 5251 st([Y,X]) #25+i*25 Draw pixel
|
|
1298 0126 ld [$26] 5252 ld([sysArgs+2]) #26+i*25 Shift byte left
|
|
1299 8200 adda ac 5253 adda(AC) #27+i*25
|
|
129a c226 st [$26] 5254 st([sysArgs+2]) #28+i*25
|
|
129b 011d ld [$1d] 5255 ld([vTmp]) #29+i*25 Unrolled loop (once)
|
|
129c 8129 adda [$29] 5256 adda([sysArgs+5]) #31+i*25
|
|
129d 9401 adda $01,y 5257 adda(1,Y) #30+i*25 Y=[sysPos+1]+[vTmp]+1
|
|
129e 0126 ld [$26] 5258 ld([sysArgs+2]) #32+i*25 Select color
|
|
129f e8a2 blt $12a2 5259 bmi(pc()+3) #33+i*25
|
|
12a0 fca3 bra $12a3 5260 bra(pc()+3) #34+i*25
|
|
12a1 0124 ld [$24] 5261 ld([sysArgs+0]) #35+i*25
|
|
12a2 0125 ld [$25] 5262 ld([sysArgs+1]) #35+i*25(!)
|
|
12a3 ce00 st [y,x] 5263 st([Y,X]) #36+i*25 Draw pixel
|
|
12a4 0126 ld [$26] 5264 ld([sysArgs+2]) #37+i*25 Shift byte left
|
|
12a5 8200 adda ac 5265 adda(AC) #38+i*25
|
|
12a6 c226 st [$26] 5266 st([sysArgs+2]) #39+i*25
|
|
12a7 011d ld [$1d] 5267 ld([vTmp]) #40+i*25 Loop counter
|
|
12a8 a006 suba $06 5268 suba(6) #41+i*25
|
|
12a9 ec90 bne .sysVdb0 5269 bne('.sysVdb0') #42+i*25
|
|
12aa 8008 adda $08 5270 adda(8) #43+i*25 Steps of 2
|
|
12ab 1403 ld $03,y 5271 ld(hi('REENTER'),Y) #119
|
|
12ac e0cb jmp y,$cb 5272 jmp(Y,'REENTER') #120
|
|
12ad 00c2 ld $c2 5273 ld(-124/2) #121
|
|
5274
|
|
5275 # SYS_ResetWaveforms_v4_50 implementation
|
|
5276 label('sys_ResetWaveforms')
|
|
sys_ResetWaveforms:
|
|
12ae 0118 ld [$18] 5277 ld([vAC+0]) #18 X=4i
|
|
12af 8200 adda ac 5278 adda(AC) #19
|
|
12b0 9200 adda ac,x 5279 adda(AC,X) #20
|
|
12b1 0118 ld [$18] 5280 ld([vAC+0]) #21
|
|
12b2 de00 st [y,x++] 5281 st([Y,Xpp]) #22 Sawtooth: T[4i+0] = i
|
|
12b3 2020 anda $20 5282 anda(0x20) #23 Triangle: T[4i+1] = 2i if i<32 else 127-2i
|
|
12b4 ecb7 bne $12b7 5283 bne(pc()+3) #24
|
|
12b5 0118 ld [$18] 5284 ld([vAC+0]) #25
|
|
12b6 fcb9 bra $12b9 5285 bra(pc()+3) #26
|
|
12b7 8118 adda [$18] 5286 adda([vAC+0]) #26,27
|
|
12b8 607f xora $7f 5287 xora(127) #27
|
|
12b9 de00 st [y,x++] 5288 st([Y,Xpp]) #28
|
|
12ba 0118 ld [$18] 5289 ld([vAC+0]) #29 Pulse: T[4i+2] = 0 if i<32 else 63
|
|
12bb 2020 anda $20 5290 anda(0x20) #30
|
|
12bc ecbf bne $12bf 5291 bne(pc()+3) #31
|
|
12bd fcc0 bra $12c0 5292 bra(pc()+3) #32
|
|
12be 0000 ld $00 5293 ld(0) #33
|
|
12bf 003f ld $3f 5294 ld(63) #33(!)
|
|
12c0 de00 st [y,x++] 5295 st([Y,Xpp]) #34
|
|
12c1 0118 ld [$18] 5296 ld([vAC+0]) #35 Sawtooth: T[4i+3] = i
|
|
12c2 ce00 st [y,x] 5297 st([Y,X]) #36
|
|
12c3 8001 adda $01 5298 adda(1) #37 i += 1
|
|
12c4 c218 st [$18] 5299 st([vAC+0]) #38
|
|
12c5 6040 xora $40 5300 xora(64) #39 For 64 iterations
|
|
12c6 f0c9 beq $12c9 5301 beq(pc()+3) #40
|
|
12c7 fcca bra $12ca 5302 bra(pc()+3) #41
|
|
12c8 00fe ld $fe 5303 ld(-2) #42
|
|
12c9 0000 ld $00 5304 ld(0) #42(!)
|
|
12ca 8116 adda [$16] 5305 adda([vPC]) #43
|
|
12cb c216 st [$16] 5306 st([vPC]) #44
|
|
12cc 1403 ld $03,y 5307 ld(hi('REENTER'),Y) #45
|
|
12cd e0cb jmp y,$cb 5308 jmp(Y,'REENTER') #46
|
|
12ce 00e7 ld $e7 5309 ld(-50/2) #47
|
|
5310
|
|
5311 # SYS_ShuffleNoise_v4_46 implementation
|
|
5312 label('sys_ShuffleNoise')
|
|
sys_ShuffleNoise:
|
|
12cf 1118 ld [$18],x 5313 ld([vAC+0],X) #18 tmp = T[4j]
|
|
12d0 0d00 ld [y,x] 5314 ld([Y,X]) #19
|
|
12d1 c21d st [$1d] 5315 st([vTmp]) #20
|
|
12d2 1119 ld [$19],x 5316 ld([vAC+1],X) #21 T[4j] = T[4i]
|
|
12d3 0d00 ld [y,x] 5317 ld([Y,X]) #22
|
|
12d4 1118 ld [$18],x 5318 ld([vAC+0],X) #23
|
|
12d5 ce00 st [y,x] 5319 st([Y,X]) #24
|
|
12d6 8200 adda ac 5320 adda(AC) #25 j += T[4i]
|
|
12d7 8200 adda ac 5321 adda(AC,) #26
|
|
12d8 8118 adda [$18] 5322 adda([vAC+0]) #27
|
|
12d9 c218 st [$18] 5323 st([vAC+0]) #28
|
|
12da 1119 ld [$19],x 5324 ld([vAC+1],X) #29 T[4i] = tmp
|
|
12db 011d ld [$1d] 5325 ld([vTmp]) #30
|
|
12dc ce00 st [y,x] 5326 st([Y,X]) #31
|
|
12dd 0119 ld [$19] 5327 ld([vAC+1]) #32 i += 1
|
|
12de 8004 adda $04 5328 adda(4) #33
|
|
12df c219 st [$19] 5329 st([vAC+1]) #34
|
|
12e0 f0e3 beq $12e3 5330 beq(pc()+3) #35 For 64 iterations
|
|
12e1 fce4 bra $12e4 5331 bra(pc()+3) #36
|
|
12e2 00fe ld $fe 5332 ld(-2) #37
|
|
12e3 0000 ld $00 5333 ld(0) #37(!)
|
|
12e4 8116 adda [$16] 5334 adda([vPC]) #38
|
|
12e5 c216 st [$16] 5335 st([vPC]) #39
|
|
12e6 1403 ld $03,y 5336 ld(hi('NEXTY'),Y) #40
|
|
12e7 e000 jmp y,$00 5337 jmp(Y,'NEXTY') #41
|
|
12e8 00ea ld $ea 5338 ld(-44/2) #42
|
|
5339
|
|
5340 # SYS_LoadBytes_DEVROM_XXX implementation
|
|
5341 label('sys_LoadBytes')
|
|
sys_LoadBytes:
|
|
12e9 0030 ld $30 5342 ld(0x30) # Target address
|
|
12ea c225 st [$25] 5343 st([sysArgs+1]) #
|
|
12eb 011a ld [$1a] 5344 ld([vLR+0]) # Source address
|
|
12ec d224 st [$24],x 5345 st([sysArgs+0],X) #
|
|
12ed 0d00 ld [y,x] 5346 ld([Y,X]) # Byte count
|
|
5347 label('.slb1') #
|
|
.slb1: 12ee c226 st [$26] 5348 st([sysArgs+2]) #
|
|
5349
|
|
12ef 0124 ld [$24] 5350 ld([sysArgs+0]) # Advance source address
|
|
12f0 8001 adda $01 5351 adda(1) #
|
|
12f1 d224 st [$24],x 5352 st([sysArgs+0],X) #
|
|
5353
|
|
12f2 0d00 ld [y,x] 5354 ld([Y,X]) # Copy byte
|
|
12f3 1125 ld [$25],x 5355 ld([sysArgs+1],X) #
|
|
12f4 c600 st [x] 5356 st([X]) #
|
|
5357
|
|
12f5 0125 ld [$25] 5358 ld([sysArgs+1]) # Advance target address
|
|
12f6 8001 adda $01 5359 adda(1) #
|
|
12f7 c225 st [$25] 5360 st([sysArgs+1]) #
|
|
5361
|
|
12f8 0126 ld [$26] 5362 ld([sysArgs+2]) # Decrement byte count and loop
|
|
12f9 ecee bne .slb1 5363 bne('.slb1') #
|
|
12fa a001 suba $01 5364 suba(1) #
|
|
5365
|
|
5366 # XXX Unfinished
|
|
5367
|
|
12fb 0200 nop 5368 align(0x100, 0x200)
|
|
12fc 0200 nop
|
|
12fd 0200 nop
|
|
* 5 times
|
|
5369 #-----------------------------------------------------------------------
|
|
5370 #
|
|
5371 # Quarter-Square table
|
|
5372 #
|
|
5373 # Used for a reasonably fast multiplication routine
|
|
5374 #-----------------------------------------------------------------------
|
|
5375 # High-bytes, stored inverted, and shifted down by 32 places
|
|
5376 for i in range(32, 256):
|
|
5377 val = math.floor(i ** 2 / 4)
|
|
5378 ld(hi(~val))
|
|
1300 00fe ld $fe ;$0100 = 256 = floor(32 ** 2 / 4); !$0100 >> 8 = $fe
|
|
1301 00fe ld $fe ;$0110 = 272 = floor(33 ** 2 / 4); !$0110 >> 8 = $fe
|
|
1302 00fe ld $fe ;$0121 = 289 = floor(34 ** 2 / 4); !$0121 >> 8 = $fe
|
|
1303 00fe ld $fe ;$0132 = 306 = floor(35 ** 2 / 4); !$0132 >> 8 = $fe
|
|
1304 00fe ld $fe ;$0144 = 324 = floor(36 ** 2 / 4); !$0144 >> 8 = $fe
|
|
1305 00fe ld $fe ;$0156 = 342 = floor(37 ** 2 / 4); !$0156 >> 8 = $fe
|
|
1306 00fe ld $fe ;$0169 = 361 = floor(38 ** 2 / 4); !$0169 >> 8 = $fe
|
|
1307 00fe ld $fe ;$017c = 380 = floor(39 ** 2 / 4); !$017c >> 8 = $fe
|
|
1308 00fe ld $fe ;$0190 = 400 = floor(40 ** 2 / 4); !$0190 >> 8 = $fe
|
|
1309 00fe ld $fe ;$01a4 = 420 = floor(41 ** 2 / 4); !$01a4 >> 8 = $fe
|
|
130a 00fe ld $fe ;$01b9 = 441 = floor(42 ** 2 / 4); !$01b9 >> 8 = $fe
|
|
130b 00fe ld $fe ;$01ce = 462 = floor(43 ** 2 / 4); !$01ce >> 8 = $fe
|
|
130c 00fe ld $fe ;$01e4 = 484 = floor(44 ** 2 / 4); !$01e4 >> 8 = $fe
|
|
130d 00fe ld $fe ;$01fa = 506 = floor(45 ** 2 / 4); !$01fa >> 8 = $fe
|
|
130e 00fd ld $fd ;$0211 = 529 = floor(46 ** 2 / 4); !$0211 >> 8 = $fd
|
|
130f 00fd ld $fd ;$0228 = 552 = floor(47 ** 2 / 4); !$0228 >> 8 = $fd
|
|
1310 00fd ld $fd ;$0240 = 576 = floor(48 ** 2 / 4); !$0240 >> 8 = $fd
|
|
1311 00fd ld $fd ;$0258 = 600 = floor(49 ** 2 / 4); !$0258 >> 8 = $fd
|
|
1312 00fd ld $fd ;$0271 = 625 = floor(50 ** 2 / 4); !$0271 >> 8 = $fd
|
|
1313 00fd ld $fd ;$028a = 650 = floor(51 ** 2 / 4); !$028a >> 8 = $fd
|
|
1314 00fd ld $fd ;$02a4 = 676 = floor(52 ** 2 / 4); !$02a4 >> 8 = $fd
|
|
1315 00fd ld $fd ;$02be = 702 = floor(53 ** 2 / 4); !$02be >> 8 = $fd
|
|
1316 00fd ld $fd ;$02d9 = 729 = floor(54 ** 2 / 4); !$02d9 >> 8 = $fd
|
|
1317 00fd ld $fd ;$02f4 = 756 = floor(55 ** 2 / 4); !$02f4 >> 8 = $fd
|
|
1318 00fc ld $fc ;$0310 = 784 = floor(56 ** 2 / 4); !$0310 >> 8 = $fc
|
|
1319 00fc ld $fc ;$032c = 812 = floor(57 ** 2 / 4); !$032c >> 8 = $fc
|
|
131a 00fc ld $fc ;$0349 = 841 = floor(58 ** 2 / 4); !$0349 >> 8 = $fc
|
|
131b 00fc ld $fc ;$0366 = 870 = floor(59 ** 2 / 4); !$0366 >> 8 = $fc
|
|
131c 00fc ld $fc ;$0384 = 900 = floor(60 ** 2 / 4); !$0384 >> 8 = $fc
|
|
131d 00fc ld $fc ;$03a2 = 930 = floor(61 ** 2 / 4); !$03a2 >> 8 = $fc
|
|
131e 00fc ld $fc ;$03c1 = 961 = floor(62 ** 2 / 4); !$03c1 >> 8 = $fc
|
|
131f 00fc ld $fc ;$03e0 = 992 = floor(63 ** 2 / 4); !$03e0 >> 8 = $fc
|
|
1320 00fb ld $fb ;$0400 = 1024 = floor(64 ** 2 / 4); !$0400 >> 8 = $fb
|
|
1321 00fb ld $fb ;$0420 = 1056 = floor(65 ** 2 / 4); !$0420 >> 8 = $fb
|
|
1322 00fb ld $fb ;$0441 = 1089 = floor(66 ** 2 / 4); !$0441 >> 8 = $fb
|
|
1323 00fb ld $fb ;$0462 = 1122 = floor(67 ** 2 / 4); !$0462 >> 8 = $fb
|
|
1324 00fb ld $fb ;$0484 = 1156 = floor(68 ** 2 / 4); !$0484 >> 8 = $fb
|
|
1325 00fb ld $fb ;$04a6 = 1190 = floor(69 ** 2 / 4); !$04a6 >> 8 = $fb
|
|
1326 00fb ld $fb ;$04c9 = 1225 = floor(70 ** 2 / 4); !$04c9 >> 8 = $fb
|
|
1327 00fb ld $fb ;$04ec = 1260 = floor(71 ** 2 / 4); !$04ec >> 8 = $fb
|
|
1328 00fa ld $fa ;$0510 = 1296 = floor(72 ** 2 / 4); !$0510 >> 8 = $fa
|
|
1329 00fa ld $fa ;$0534 = 1332 = floor(73 ** 2 / 4); !$0534 >> 8 = $fa
|
|
132a 00fa ld $fa ;$0559 = 1369 = floor(74 ** 2 / 4); !$0559 >> 8 = $fa
|
|
132b 00fa ld $fa ;$057e = 1406 = floor(75 ** 2 / 4); !$057e >> 8 = $fa
|
|
132c 00fa ld $fa ;$05a4 = 1444 = floor(76 ** 2 / 4); !$05a4 >> 8 = $fa
|
|
132d 00fa ld $fa ;$05ca = 1482 = floor(77 ** 2 / 4); !$05ca >> 8 = $fa
|
|
132e 00fa ld $fa ;$05f1 = 1521 = floor(78 ** 2 / 4); !$05f1 >> 8 = $fa
|
|
132f 00f9 ld $f9 ;$0618 = 1560 = floor(79 ** 2 / 4); !$0618 >> 8 = $f9
|
|
1330 00f9 ld $f9 ;$0640 = 1600 = floor(80 ** 2 / 4); !$0640 >> 8 = $f9
|
|
1331 00f9 ld $f9 ;$0668 = 1640 = floor(81 ** 2 / 4); !$0668 >> 8 = $f9
|
|
1332 00f9 ld $f9 ;$0691 = 1681 = floor(82 ** 2 / 4); !$0691 >> 8 = $f9
|
|
1333 00f9 ld $f9 ;$06ba = 1722 = floor(83 ** 2 / 4); !$06ba >> 8 = $f9
|
|
1334 00f9 ld $f9 ;$06e4 = 1764 = floor(84 ** 2 / 4); !$06e4 >> 8 = $f9
|
|
1335 00f8 ld $f8 ;$070e = 1806 = floor(85 ** 2 / 4); !$070e >> 8 = $f8
|
|
1336 00f8 ld $f8 ;$0739 = 1849 = floor(86 ** 2 / 4); !$0739 >> 8 = $f8
|
|
1337 00f8 ld $f8 ;$0764 = 1892 = floor(87 ** 2 / 4); !$0764 >> 8 = $f8
|
|
1338 00f8 ld $f8 ;$0790 = 1936 = floor(88 ** 2 / 4); !$0790 >> 8 = $f8
|
|
1339 00f8 ld $f8 ;$07bc = 1980 = floor(89 ** 2 / 4); !$07bc >> 8 = $f8
|
|
133a 00f8 ld $f8 ;$07e9 = 2025 = floor(90 ** 2 / 4); !$07e9 >> 8 = $f8
|
|
133b 00f7 ld $f7 ;$0816 = 2070 = floor(91 ** 2 / 4); !$0816 >> 8 = $f7
|
|
133c 00f7 ld $f7 ;$0844 = 2116 = floor(92 ** 2 / 4); !$0844 >> 8 = $f7
|
|
133d 00f7 ld $f7 ;$0872 = 2162 = floor(93 ** 2 / 4); !$0872 >> 8 = $f7
|
|
133e 00f7 ld $f7 ;$08a1 = 2209 = floor(94 ** 2 / 4); !$08a1 >> 8 = $f7
|
|
133f 00f7 ld $f7 ;$08d0 = 2256 = floor(95 ** 2 / 4); !$08d0 >> 8 = $f7
|
|
1340 00f6 ld $f6 ;$0900 = 2304 = floor(96 ** 2 / 4); !$0900 >> 8 = $f6
|
|
1341 00f6 ld $f6 ;$0930 = 2352 = floor(97 ** 2 / 4); !$0930 >> 8 = $f6
|
|
1342 00f6 ld $f6 ;$0961 = 2401 = floor(98 ** 2 / 4); !$0961 >> 8 = $f6
|
|
1343 00f6 ld $f6 ;$0992 = 2450 = floor(99 ** 2 / 4); !$0992 >> 8 = $f6
|
|
1344 00f6 ld $f6 ;$09c4 = 2500 = floor(100 ** 2 / 4); !$09c4 >> 8 = $f6
|
|
1345 00f6 ld $f6 ;$09f6 = 2550 = floor(101 ** 2 / 4); !$09f6 >> 8 = $f6
|
|
1346 00f5 ld $f5 ;$0a29 = 2601 = floor(102 ** 2 / 4); !$0a29 >> 8 = $f5
|
|
1347 00f5 ld $f5 ;$0a5c = 2652 = floor(103 ** 2 / 4); !$0a5c >> 8 = $f5
|
|
1348 00f5 ld $f5 ;$0a90 = 2704 = floor(104 ** 2 / 4); !$0a90 >> 8 = $f5
|
|
1349 00f5 ld $f5 ;$0ac4 = 2756 = floor(105 ** 2 / 4); !$0ac4 >> 8 = $f5
|
|
134a 00f5 ld $f5 ;$0af9 = 2809 = floor(106 ** 2 / 4); !$0af9 >> 8 = $f5
|
|
134b 00f4 ld $f4 ;$0b2e = 2862 = floor(107 ** 2 / 4); !$0b2e >> 8 = $f4
|
|
134c 00f4 ld $f4 ;$0b64 = 2916 = floor(108 ** 2 / 4); !$0b64 >> 8 = $f4
|
|
134d 00f4 ld $f4 ;$0b9a = 2970 = floor(109 ** 2 / 4); !$0b9a >> 8 = $f4
|
|
134e 00f4 ld $f4 ;$0bd1 = 3025 = floor(110 ** 2 / 4); !$0bd1 >> 8 = $f4
|
|
134f 00f3 ld $f3 ;$0c08 = 3080 = floor(111 ** 2 / 4); !$0c08 >> 8 = $f3
|
|
1350 00f3 ld $f3 ;$0c40 = 3136 = floor(112 ** 2 / 4); !$0c40 >> 8 = $f3
|
|
1351 00f3 ld $f3 ;$0c78 = 3192 = floor(113 ** 2 / 4); !$0c78 >> 8 = $f3
|
|
1352 00f3 ld $f3 ;$0cb1 = 3249 = floor(114 ** 2 / 4); !$0cb1 >> 8 = $f3
|
|
1353 00f3 ld $f3 ;$0cea = 3306 = floor(115 ** 2 / 4); !$0cea >> 8 = $f3
|
|
1354 00f2 ld $f2 ;$0d24 = 3364 = floor(116 ** 2 / 4); !$0d24 >> 8 = $f2
|
|
1355 00f2 ld $f2 ;$0d5e = 3422 = floor(117 ** 2 / 4); !$0d5e >> 8 = $f2
|
|
1356 00f2 ld $f2 ;$0d99 = 3481 = floor(118 ** 2 / 4); !$0d99 >> 8 = $f2
|
|
1357 00f2 ld $f2 ;$0dd4 = 3540 = floor(119 ** 2 / 4); !$0dd4 >> 8 = $f2
|
|
1358 00f1 ld $f1 ;$0e10 = 3600 = floor(120 ** 2 / 4); !$0e10 >> 8 = $f1
|
|
1359 00f1 ld $f1 ;$0e4c = 3660 = floor(121 ** 2 / 4); !$0e4c >> 8 = $f1
|
|
135a 00f1 ld $f1 ;$0e89 = 3721 = floor(122 ** 2 / 4); !$0e89 >> 8 = $f1
|
|
135b 00f1 ld $f1 ;$0ec6 = 3782 = floor(123 ** 2 / 4); !$0ec6 >> 8 = $f1
|
|
135c 00f0 ld $f0 ;$0f04 = 3844 = floor(124 ** 2 / 4); !$0f04 >> 8 = $f0
|
|
135d 00f0 ld $f0 ;$0f42 = 3906 = floor(125 ** 2 / 4); !$0f42 >> 8 = $f0
|
|
135e 00f0 ld $f0 ;$0f81 = 3969 = floor(126 ** 2 / 4); !$0f81 >> 8 = $f0
|
|
135f 00f0 ld $f0 ;$0fc0 = 4032 = floor(127 ** 2 / 4); !$0fc0 >> 8 = $f0
|
|
1360 00ef ld $ef ;$1000 = 4096 = floor(128 ** 2 / 4); !$1000 >> 8 = $ef
|
|
1361 00ef ld $ef ;$1040 = 4160 = floor(129 ** 2 / 4); !$1040 >> 8 = $ef
|
|
1362 00ef ld $ef ;$1081 = 4225 = floor(130 ** 2 / 4); !$1081 >> 8 = $ef
|
|
1363 00ef ld $ef ;$10c2 = 4290 = floor(131 ** 2 / 4); !$10c2 >> 8 = $ef
|
|
1364 00ee ld $ee ;$1104 = 4356 = floor(132 ** 2 / 4); !$1104 >> 8 = $ee
|
|
1365 00ee ld $ee ;$1146 = 4422 = floor(133 ** 2 / 4); !$1146 >> 8 = $ee
|
|
1366 00ee ld $ee ;$1189 = 4489 = floor(134 ** 2 / 4); !$1189 >> 8 = $ee
|
|
1367 00ee ld $ee ;$11cc = 4556 = floor(135 ** 2 / 4); !$11cc >> 8 = $ee
|
|
1368 00ed ld $ed ;$1210 = 4624 = floor(136 ** 2 / 4); !$1210 >> 8 = $ed
|
|
1369 00ed ld $ed ;$1254 = 4692 = floor(137 ** 2 / 4); !$1254 >> 8 = $ed
|
|
136a 00ed ld $ed ;$1299 = 4761 = floor(138 ** 2 / 4); !$1299 >> 8 = $ed
|
|
136b 00ed ld $ed ;$12de = 4830 = floor(139 ** 2 / 4); !$12de >> 8 = $ed
|
|
136c 00ec ld $ec ;$1324 = 4900 = floor(140 ** 2 / 4); !$1324 >> 8 = $ec
|
|
136d 00ec ld $ec ;$136a = 4970 = floor(141 ** 2 / 4); !$136a >> 8 = $ec
|
|
136e 00ec ld $ec ;$13b1 = 5041 = floor(142 ** 2 / 4); !$13b1 >> 8 = $ec
|
|
136f 00ec ld $ec ;$13f8 = 5112 = floor(143 ** 2 / 4); !$13f8 >> 8 = $ec
|
|
1370 00eb ld $eb ;$1440 = 5184 = floor(144 ** 2 / 4); !$1440 >> 8 = $eb
|
|
1371 00eb ld $eb ;$1488 = 5256 = floor(145 ** 2 / 4); !$1488 >> 8 = $eb
|
|
1372 00eb ld $eb ;$14d1 = 5329 = floor(146 ** 2 / 4); !$14d1 >> 8 = $eb
|
|
1373 00ea ld $ea ;$151a = 5402 = floor(147 ** 2 / 4); !$151a >> 8 = $ea
|
|
1374 00ea ld $ea ;$1564 = 5476 = floor(148 ** 2 / 4); !$1564 >> 8 = $ea
|
|
1375 00ea ld $ea ;$15ae = 5550 = floor(149 ** 2 / 4); !$15ae >> 8 = $ea
|
|
1376 00ea ld $ea ;$15f9 = 5625 = floor(150 ** 2 / 4); !$15f9 >> 8 = $ea
|
|
1377 00e9 ld $e9 ;$1644 = 5700 = floor(151 ** 2 / 4); !$1644 >> 8 = $e9
|
|
1378 00e9 ld $e9 ;$1690 = 5776 = floor(152 ** 2 / 4); !$1690 >> 8 = $e9
|
|
1379 00e9 ld $e9 ;$16dc = 5852 = floor(153 ** 2 / 4); !$16dc >> 8 = $e9
|
|
137a 00e8 ld $e8 ;$1729 = 5929 = floor(154 ** 2 / 4); !$1729 >> 8 = $e8
|
|
137b 00e8 ld $e8 ;$1776 = 6006 = floor(155 ** 2 / 4); !$1776 >> 8 = $e8
|
|
137c 00e8 ld $e8 ;$17c4 = 6084 = floor(156 ** 2 / 4); !$17c4 >> 8 = $e8
|
|
137d 00e7 ld $e7 ;$1812 = 6162 = floor(157 ** 2 / 4); !$1812 >> 8 = $e7
|
|
137e 00e7 ld $e7 ;$1861 = 6241 = floor(158 ** 2 / 4); !$1861 >> 8 = $e7
|
|
137f 00e7 ld $e7 ;$18b0 = 6320 = floor(159 ** 2 / 4); !$18b0 >> 8 = $e7
|
|
1380 00e6 ld $e6 ;$1900 = 6400 = floor(160 ** 2 / 4); !$1900 >> 8 = $e6
|
|
1381 00e6 ld $e6 ;$1950 = 6480 = floor(161 ** 2 / 4); !$1950 >> 8 = $e6
|
|
1382 00e6 ld $e6 ;$19a1 = 6561 = floor(162 ** 2 / 4); !$19a1 >> 8 = $e6
|
|
1383 00e6 ld $e6 ;$19f2 = 6642 = floor(163 ** 2 / 4); !$19f2 >> 8 = $e6
|
|
1384 00e5 ld $e5 ;$1a44 = 6724 = floor(164 ** 2 / 4); !$1a44 >> 8 = $e5
|
|
1385 00e5 ld $e5 ;$1a96 = 6806 = floor(165 ** 2 / 4); !$1a96 >> 8 = $e5
|
|
1386 00e5 ld $e5 ;$1ae9 = 6889 = floor(166 ** 2 / 4); !$1ae9 >> 8 = $e5
|
|
1387 00e4 ld $e4 ;$1b3c = 6972 = floor(167 ** 2 / 4); !$1b3c >> 8 = $e4
|
|
1388 00e4 ld $e4 ;$1b90 = 7056 = floor(168 ** 2 / 4); !$1b90 >> 8 = $e4
|
|
1389 00e4 ld $e4 ;$1be4 = 7140 = floor(169 ** 2 / 4); !$1be4 >> 8 = $e4
|
|
138a 00e3 ld $e3 ;$1c39 = 7225 = floor(170 ** 2 / 4); !$1c39 >> 8 = $e3
|
|
138b 00e3 ld $e3 ;$1c8e = 7310 = floor(171 ** 2 / 4); !$1c8e >> 8 = $e3
|
|
138c 00e3 ld $e3 ;$1ce4 = 7396 = floor(172 ** 2 / 4); !$1ce4 >> 8 = $e3
|
|
138d 00e2 ld $e2 ;$1d3a = 7482 = floor(173 ** 2 / 4); !$1d3a >> 8 = $e2
|
|
138e 00e2 ld $e2 ;$1d91 = 7569 = floor(174 ** 2 / 4); !$1d91 >> 8 = $e2
|
|
138f 00e2 ld $e2 ;$1de8 = 7656 = floor(175 ** 2 / 4); !$1de8 >> 8 = $e2
|
|
1390 00e1 ld $e1 ;$1e40 = 7744 = floor(176 ** 2 / 4); !$1e40 >> 8 = $e1
|
|
1391 00e1 ld $e1 ;$1e98 = 7832 = floor(177 ** 2 / 4); !$1e98 >> 8 = $e1
|
|
1392 00e1 ld $e1 ;$1ef1 = 7921 = floor(178 ** 2 / 4); !$1ef1 >> 8 = $e1
|
|
1393 00e0 ld $e0 ;$1f4a = 8010 = floor(179 ** 2 / 4); !$1f4a >> 8 = $e0
|
|
1394 00e0 ld $e0 ;$1fa4 = 8100 = floor(180 ** 2 / 4); !$1fa4 >> 8 = $e0
|
|
1395 00e0 ld $e0 ;$1ffe = 8190 = floor(181 ** 2 / 4); !$1ffe >> 8 = $e0
|
|
1396 00df ld $df ;$2059 = 8281 = floor(182 ** 2 / 4); !$2059 >> 8 = $df
|
|
1397 00df ld $df ;$20b4 = 8372 = floor(183 ** 2 / 4); !$20b4 >> 8 = $df
|
|
1398 00de ld $de ;$2110 = 8464 = floor(184 ** 2 / 4); !$2110 >> 8 = $de
|
|
1399 00de ld $de ;$216c = 8556 = floor(185 ** 2 / 4); !$216c >> 8 = $de
|
|
139a 00de ld $de ;$21c9 = 8649 = floor(186 ** 2 / 4); !$21c9 >> 8 = $de
|
|
139b 00dd ld $dd ;$2226 = 8742 = floor(187 ** 2 / 4); !$2226 >> 8 = $dd
|
|
139c 00dd ld $dd ;$2284 = 8836 = floor(188 ** 2 / 4); !$2284 >> 8 = $dd
|
|
139d 00dd ld $dd ;$22e2 = 8930 = floor(189 ** 2 / 4); !$22e2 >> 8 = $dd
|
|
139e 00dc ld $dc ;$2341 = 9025 = floor(190 ** 2 / 4); !$2341 >> 8 = $dc
|
|
139f 00dc ld $dc ;$23a0 = 9120 = floor(191 ** 2 / 4); !$23a0 >> 8 = $dc
|
|
13a0 00db ld $db ;$2400 = 9216 = floor(192 ** 2 / 4); !$2400 >> 8 = $db
|
|
13a1 00db ld $db ;$2460 = 9312 = floor(193 ** 2 / 4); !$2460 >> 8 = $db
|
|
13a2 00db ld $db ;$24c1 = 9409 = floor(194 ** 2 / 4); !$24c1 >> 8 = $db
|
|
13a3 00da ld $da ;$2522 = 9506 = floor(195 ** 2 / 4); !$2522 >> 8 = $da
|
|
13a4 00da ld $da ;$2584 = 9604 = floor(196 ** 2 / 4); !$2584 >> 8 = $da
|
|
13a5 00da ld $da ;$25e6 = 9702 = floor(197 ** 2 / 4); !$25e6 >> 8 = $da
|
|
13a6 00d9 ld $d9 ;$2649 = 9801 = floor(198 ** 2 / 4); !$2649 >> 8 = $d9
|
|
13a7 00d9 ld $d9 ;$26ac = 9900 = floor(199 ** 2 / 4); !$26ac >> 8 = $d9
|
|
13a8 00d8 ld $d8 ;$2710 = 10000 = floor(200 ** 2 / 4); !$2710 >> 8 = $d8
|
|
13a9 00d8 ld $d8 ;$2774 = 10100 = floor(201 ** 2 / 4); !$2774 >> 8 = $d8
|
|
13aa 00d8 ld $d8 ;$27d9 = 10201 = floor(202 ** 2 / 4); !$27d9 >> 8 = $d8
|
|
13ab 00d7 ld $d7 ;$283e = 10302 = floor(203 ** 2 / 4); !$283e >> 8 = $d7
|
|
13ac 00d7 ld $d7 ;$28a4 = 10404 = floor(204 ** 2 / 4); !$28a4 >> 8 = $d7
|
|
13ad 00d6 ld $d6 ;$290a = 10506 = floor(205 ** 2 / 4); !$290a >> 8 = $d6
|
|
13ae 00d6 ld $d6 ;$2971 = 10609 = floor(206 ** 2 / 4); !$2971 >> 8 = $d6
|
|
13af 00d6 ld $d6 ;$29d8 = 10712 = floor(207 ** 2 / 4); !$29d8 >> 8 = $d6
|
|
13b0 00d5 ld $d5 ;$2a40 = 10816 = floor(208 ** 2 / 4); !$2a40 >> 8 = $d5
|
|
13b1 00d5 ld $d5 ;$2aa8 = 10920 = floor(209 ** 2 / 4); !$2aa8 >> 8 = $d5
|
|
13b2 00d4 ld $d4 ;$2b11 = 11025 = floor(210 ** 2 / 4); !$2b11 >> 8 = $d4
|
|
13b3 00d4 ld $d4 ;$2b7a = 11130 = floor(211 ** 2 / 4); !$2b7a >> 8 = $d4
|
|
13b4 00d4 ld $d4 ;$2be4 = 11236 = floor(212 ** 2 / 4); !$2be4 >> 8 = $d4
|
|
13b5 00d3 ld $d3 ;$2c4e = 11342 = floor(213 ** 2 / 4); !$2c4e >> 8 = $d3
|
|
13b6 00d3 ld $d3 ;$2cb9 = 11449 = floor(214 ** 2 / 4); !$2cb9 >> 8 = $d3
|
|
13b7 00d2 ld $d2 ;$2d24 = 11556 = floor(215 ** 2 / 4); !$2d24 >> 8 = $d2
|
|
13b8 00d2 ld $d2 ;$2d90 = 11664 = floor(216 ** 2 / 4); !$2d90 >> 8 = $d2
|
|
13b9 00d2 ld $d2 ;$2dfc = 11772 = floor(217 ** 2 / 4); !$2dfc >> 8 = $d2
|
|
13ba 00d1 ld $d1 ;$2e69 = 11881 = floor(218 ** 2 / 4); !$2e69 >> 8 = $d1
|
|
13bb 00d1 ld $d1 ;$2ed6 = 11990 = floor(219 ** 2 / 4); !$2ed6 >> 8 = $d1
|
|
13bc 00d0 ld $d0 ;$2f44 = 12100 = floor(220 ** 2 / 4); !$2f44 >> 8 = $d0
|
|
13bd 00d0 ld $d0 ;$2fb2 = 12210 = floor(221 ** 2 / 4); !$2fb2 >> 8 = $d0
|
|
13be 00cf ld $cf ;$3021 = 12321 = floor(222 ** 2 / 4); !$3021 >> 8 = $cf
|
|
13bf 00cf ld $cf ;$3090 = 12432 = floor(223 ** 2 / 4); !$3090 >> 8 = $cf
|
|
13c0 00ce ld $ce ;$3100 = 12544 = floor(224 ** 2 / 4); !$3100 >> 8 = $ce
|
|
13c1 00ce ld $ce ;$3170 = 12656 = floor(225 ** 2 / 4); !$3170 >> 8 = $ce
|
|
13c2 00ce ld $ce ;$31e1 = 12769 = floor(226 ** 2 / 4); !$31e1 >> 8 = $ce
|
|
13c3 00cd ld $cd ;$3252 = 12882 = floor(227 ** 2 / 4); !$3252 >> 8 = $cd
|
|
13c4 00cd ld $cd ;$32c4 = 12996 = floor(228 ** 2 / 4); !$32c4 >> 8 = $cd
|
|
13c5 00cc ld $cc ;$3336 = 13110 = floor(229 ** 2 / 4); !$3336 >> 8 = $cc
|
|
13c6 00cc ld $cc ;$33a9 = 13225 = floor(230 ** 2 / 4); !$33a9 >> 8 = $cc
|
|
13c7 00cb ld $cb ;$341c = 13340 = floor(231 ** 2 / 4); !$341c >> 8 = $cb
|
|
13c8 00cb ld $cb ;$3490 = 13456 = floor(232 ** 2 / 4); !$3490 >> 8 = $cb
|
|
13c9 00ca ld $ca ;$3504 = 13572 = floor(233 ** 2 / 4); !$3504 >> 8 = $ca
|
|
13ca 00ca ld $ca ;$3579 = 13689 = floor(234 ** 2 / 4); !$3579 >> 8 = $ca
|
|
13cb 00ca ld $ca ;$35ee = 13806 = floor(235 ** 2 / 4); !$35ee >> 8 = $ca
|
|
13cc 00c9 ld $c9 ;$3664 = 13924 = floor(236 ** 2 / 4); !$3664 >> 8 = $c9
|
|
13cd 00c9 ld $c9 ;$36da = 14042 = floor(237 ** 2 / 4); !$36da >> 8 = $c9
|
|
13ce 00c8 ld $c8 ;$3751 = 14161 = floor(238 ** 2 / 4); !$3751 >> 8 = $c8
|
|
13cf 00c8 ld $c8 ;$37c8 = 14280 = floor(239 ** 2 / 4); !$37c8 >> 8 = $c8
|
|
13d0 00c7 ld $c7 ;$3840 = 14400 = floor(240 ** 2 / 4); !$3840 >> 8 = $c7
|
|
13d1 00c7 ld $c7 ;$38b8 = 14520 = floor(241 ** 2 / 4); !$38b8 >> 8 = $c7
|
|
13d2 00c6 ld $c6 ;$3931 = 14641 = floor(242 ** 2 / 4); !$3931 >> 8 = $c6
|
|
13d3 00c6 ld $c6 ;$39aa = 14762 = floor(243 ** 2 / 4); !$39aa >> 8 = $c6
|
|
13d4 00c5 ld $c5 ;$3a24 = 14884 = floor(244 ** 2 / 4); !$3a24 >> 8 = $c5
|
|
13d5 00c5 ld $c5 ;$3a9e = 15006 = floor(245 ** 2 / 4); !$3a9e >> 8 = $c5
|
|
13d6 00c4 ld $c4 ;$3b19 = 15129 = floor(246 ** 2 / 4); !$3b19 >> 8 = $c4
|
|
13d7 00c4 ld $c4 ;$3b94 = 15252 = floor(247 ** 2 / 4); !$3b94 >> 8 = $c4
|
|
13d8 00c3 ld $c3 ;$3c10 = 15376 = floor(248 ** 2 / 4); !$3c10 >> 8 = $c3
|
|
13d9 00c3 ld $c3 ;$3c8c = 15500 = floor(249 ** 2 / 4); !$3c8c >> 8 = $c3
|
|
13da 00c2 ld $c2 ;$3d09 = 15625 = floor(250 ** 2 / 4); !$3d09 >> 8 = $c2
|
|
13db 00c2 ld $c2 ;$3d86 = 15750 = floor(251 ** 2 / 4); !$3d86 >> 8 = $c2
|
|
13dc 00c1 ld $c1 ;$3e04 = 15876 = floor(252 ** 2 / 4); !$3e04 >> 8 = $c1
|
|
13dd 00c1 ld $c1 ;$3e82 = 16002 = floor(253 ** 2 / 4); !$3e82 >> 8 = $c1
|
|
13de 00c0 ld $c0 ;$3f01 = 16129 = floor(254 ** 2 / 4); !$3f01 >> 8 = $c0
|
|
13df 00c0 ld $c0 ;$3f80 = 16256 = floor(255 ** 2 / 4); !$3f80 >> 8 = $c0
|
|
5379 C(f"${val:04x} = {val} = floor({i} ** 2 / 4); !${val:04x} >> 8 = ${(~val & 0xffff) >> 8:02x}")
|
|
5380 # Return to code
|
|
5381 label("sys_MultiplyBytes.tableExit")
|
|
sys_MultiplyBytes.tableExit:
|
|
13e0 1415 ld $15,y 5382 ld(hi("sys_MultiplyBytes#44"), Y) #41,65
|
|
13e1 e129 jmp y,[$29] 5383 jmp(Y, [sysArgs + 5]) #42,66
|
|
13e2 1413 ld $13,y 5384 ld(hi(pc()), Y) #43,67
|
|
5385 # Implementation of sysMultiplyBytes
|
|
5386 label("SYS_MultiplyBytes_120")
|
|
SYS_MultiplyBytes_120:
|
|
13e3 00fd ld $fd 5387 ld("sys_MultiplyBytes.high-byte-action.store-inverted") #15
|
|
13e4 c228 st [$28] 5388 st([sysArgs + 4]) #16
|
|
13e5 0000 ld $00 5389 ld("sys_MultiplyBytes#44") #17
|
|
13e6 c229 st [$29] 5390 st([sysArgs + 5]) #18
|
|
13e7 0124 ld [$24] 5391 ld([sysArgs + 0]) #19
|
|
13e8 207f anda $7f 5392 anda(0b0111_1111) #20
|
|
13e9 c226 st [$26] 5393 st([sysArgs + 2]) #21
|
|
13ea 0125 ld [$25] 5394 ld([sysArgs + 1]) #22
|
|
13eb 207f anda $7f 5395 anda(0b0111_1111) #23
|
|
13ec c227 st [$27] 5396 st([sysArgs + 3]) #24
|
|
13ed a126 suba [$26] 5397 suba([sysArgs + 2]) #25
|
|
13ee e8f1 blt $13f1 5398 blt(pc() + 3) #26
|
|
13ef fcf2 bra $13f2 5399 bra(pc() + 3) #27
|
|
13f0 a001 suba $01 5400 suba(1) #28
|
|
13f1 60ff xora $ff 5401 xora(0xFF) #28
|
|
13f2 8001 adda $01 5402 adda(1) #29
|
|
5403 label("sys_MultiplyBytes.tableEntry")
|
|
sys_MultiplyBytes.tableEntry:
|
|
13f3 c21d st [$1d] 5404 st([vTmp]) #30,52
|
|
13f4 e8f9 blt $13f9 5405 blt(pc() + 5) #31,53
|
|
13f5 a020 suba $20 5406 suba(32) #32,54
|
|
13f6 f600 bge ac 5407 bge(AC) #33,55
|
|
13f7 fd28 bra [$28] 5408 bra([sysArgs + 4]) #34,56
|
|
13f8 00ff ld $ff 5409 ld(0xff) #35,57
|
|
13f9 fe00 bra ac 5410 bra(AC) #33,55
|
|
13fa fd28 bra [$28] 5411 bra([sysArgs + 4]) #34,56
|
|
5412 fillers(until=251)
|
|
5413 label("sys_MultiplyBytes.high-byte-action.restore-and-add")
|
|
sys_MultiplyBytes.high-byte-action.restore-and-add:
|
|
13fb 60ff xora $ff 5414 xora(0xFF) #58
|
|
13fc 8119 adda [$19] 5415 adda([vAC + 1]) #59
|
|
5416 label("sys_MultiplyBytes.high-byte-action.store-inverted")
|
|
sys_MultiplyBytes.high-byte-action.store-inverted:
|
|
13fd c219 st [$19] 5417 st([vAC + 1]) #36,60
|
|
13fe 011d ld [$1d] 5418 ld([vTmp]) #37,61
|
|
5419 assert pc() & 0xFF == 0xFF, pc()
|
|
13ff ee00 bne ac 5420 bne(AC) #38,62
|
|
1400 e0e0 jmp y,$e0 5421 jmp(Y, "sys_MultiplyBytes.tableExit") #39,63
|
|
5422 ld(0xff) #40,64
|
|
1401 00ff ld $ff ;0 = floor(0 ** 2 / 4) and floor(1 ** 2 / 4); !$0 = $ff
|
|
5423
|
|
5424 # Low-bytes, stored inverted.
|
|
5425 C("0 = floor(0 ** 2 / 4) and floor(1 ** 2 / 4); !$0 = $ff")
|
|
5426 for i in range(2, 256):
|
|
5427 val = math.floor(i ** 2 / 4)
|
|
5428 ld(~val)
|
|
1402 00fe ld $fe ;$0001 = 1 = floor(2 ** 2 / 4); !$01 = $fe
|
|
1403 00fd ld $fd ;$0002 = 2 = floor(3 ** 2 / 4); !$02 = $fd
|
|
1404 00fb ld $fb ;$0004 = 4 = floor(4 ** 2 / 4); !$04 = $fb
|
|
1405 00f9 ld $f9 ;$0006 = 6 = floor(5 ** 2 / 4); !$06 = $f9
|
|
1406 00f6 ld $f6 ;$0009 = 9 = floor(6 ** 2 / 4); !$09 = $f6
|
|
1407 00f3 ld $f3 ;$000c = 12 = floor(7 ** 2 / 4); !$0c = $f3
|
|
1408 00ef ld $ef ;$0010 = 16 = floor(8 ** 2 / 4); !$10 = $ef
|
|
1409 00eb ld $eb ;$0014 = 20 = floor(9 ** 2 / 4); !$14 = $eb
|
|
140a 00e6 ld $e6 ;$0019 = 25 = floor(10 ** 2 / 4); !$19 = $e6
|
|
140b 00e1 ld $e1 ;$001e = 30 = floor(11 ** 2 / 4); !$1e = $e1
|
|
140c 00db ld $db ;$0024 = 36 = floor(12 ** 2 / 4); !$24 = $db
|
|
140d 00d5 ld $d5 ;$002a = 42 = floor(13 ** 2 / 4); !$2a = $d5
|
|
140e 00ce ld $ce ;$0031 = 49 = floor(14 ** 2 / 4); !$31 = $ce
|
|
140f 00c7 ld $c7 ;$0038 = 56 = floor(15 ** 2 / 4); !$38 = $c7
|
|
1410 00bf ld $bf ;$0040 = 64 = floor(16 ** 2 / 4); !$40 = $bf
|
|
1411 00b7 ld $b7 ;$0048 = 72 = floor(17 ** 2 / 4); !$48 = $b7
|
|
1412 00ae ld $ae ;$0051 = 81 = floor(18 ** 2 / 4); !$51 = $ae
|
|
1413 00a5 ld $a5 ;$005a = 90 = floor(19 ** 2 / 4); !$5a = $a5
|
|
1414 009b ld $9b ;$0064 = 100 = floor(20 ** 2 / 4); !$64 = $9b
|
|
1415 0091 ld $91 ;$006e = 110 = floor(21 ** 2 / 4); !$6e = $91
|
|
1416 0086 ld $86 ;$0079 = 121 = floor(22 ** 2 / 4); !$79 = $86
|
|
1417 007b ld $7b ;$0084 = 132 = floor(23 ** 2 / 4); !$84 = $7b
|
|
1418 006f ld $6f ;$0090 = 144 = floor(24 ** 2 / 4); !$90 = $6f
|
|
1419 0063 ld $63 ;$009c = 156 = floor(25 ** 2 / 4); !$9c = $63
|
|
141a 0056 ld $56 ;$00a9 = 169 = floor(26 ** 2 / 4); !$a9 = $56
|
|
141b 0049 ld $49 ;$00b6 = 182 = floor(27 ** 2 / 4); !$b6 = $49
|
|
141c 003b ld $3b ;$00c4 = 196 = floor(28 ** 2 / 4); !$c4 = $3b
|
|
141d 002d ld $2d ;$00d2 = 210 = floor(29 ** 2 / 4); !$d2 = $2d
|
|
141e 001e ld $1e ;$00e1 = 225 = floor(30 ** 2 / 4); !$e1 = $1e
|
|
141f 000f ld $0f ;$00f0 = 240 = floor(31 ** 2 / 4); !$f0 = $0f
|
|
1420 00ff ld $ff ;$0100 = 256 = floor(32 ** 2 / 4); !$100 = $ff
|
|
1421 00ef ld $ef ;$0110 = 272 = floor(33 ** 2 / 4); !$110 = $ef
|
|
1422 00de ld $de ;$0121 = 289 = floor(34 ** 2 / 4); !$121 = $de
|
|
1423 00cd ld $cd ;$0132 = 306 = floor(35 ** 2 / 4); !$132 = $cd
|
|
1424 00bb ld $bb ;$0144 = 324 = floor(36 ** 2 / 4); !$144 = $bb
|
|
1425 00a9 ld $a9 ;$0156 = 342 = floor(37 ** 2 / 4); !$156 = $a9
|
|
1426 0096 ld $96 ;$0169 = 361 = floor(38 ** 2 / 4); !$169 = $96
|
|
1427 0083 ld $83 ;$017c = 380 = floor(39 ** 2 / 4); !$17c = $83
|
|
1428 006f ld $6f ;$0190 = 400 = floor(40 ** 2 / 4); !$190 = $6f
|
|
1429 005b ld $5b ;$01a4 = 420 = floor(41 ** 2 / 4); !$1a4 = $5b
|
|
142a 0046 ld $46 ;$01b9 = 441 = floor(42 ** 2 / 4); !$1b9 = $46
|
|
142b 0031 ld $31 ;$01ce = 462 = floor(43 ** 2 / 4); !$1ce = $31
|
|
142c 001b ld $1b ;$01e4 = 484 = floor(44 ** 2 / 4); !$1e4 = $1b
|
|
142d 0005 ld $05 ;$01fa = 506 = floor(45 ** 2 / 4); !$1fa = $05
|
|
142e 00ee ld $ee ;$0211 = 529 = floor(46 ** 2 / 4); !$211 = $ee
|
|
142f 00d7 ld $d7 ;$0228 = 552 = floor(47 ** 2 / 4); !$228 = $d7
|
|
1430 00bf ld $bf ;$0240 = 576 = floor(48 ** 2 / 4); !$240 = $bf
|
|
1431 00a7 ld $a7 ;$0258 = 600 = floor(49 ** 2 / 4); !$258 = $a7
|
|
1432 008e ld $8e ;$0271 = 625 = floor(50 ** 2 / 4); !$271 = $8e
|
|
1433 0075 ld $75 ;$028a = 650 = floor(51 ** 2 / 4); !$28a = $75
|
|
1434 005b ld $5b ;$02a4 = 676 = floor(52 ** 2 / 4); !$2a4 = $5b
|
|
1435 0041 ld $41 ;$02be = 702 = floor(53 ** 2 / 4); !$2be = $41
|
|
1436 0026 ld $26 ;$02d9 = 729 = floor(54 ** 2 / 4); !$2d9 = $26
|
|
1437 000b ld $0b ;$02f4 = 756 = floor(55 ** 2 / 4); !$2f4 = $0b
|
|
1438 00ef ld $ef ;$0310 = 784 = floor(56 ** 2 / 4); !$310 = $ef
|
|
1439 00d3 ld $d3 ;$032c = 812 = floor(57 ** 2 / 4); !$32c = $d3
|
|
143a 00b6 ld $b6 ;$0349 = 841 = floor(58 ** 2 / 4); !$349 = $b6
|
|
143b 0099 ld $99 ;$0366 = 870 = floor(59 ** 2 / 4); !$366 = $99
|
|
143c 007b ld $7b ;$0384 = 900 = floor(60 ** 2 / 4); !$384 = $7b
|
|
143d 005d ld $5d ;$03a2 = 930 = floor(61 ** 2 / 4); !$3a2 = $5d
|
|
143e 003e ld $3e ;$03c1 = 961 = floor(62 ** 2 / 4); !$3c1 = $3e
|
|
143f 001f ld $1f ;$03e0 = 992 = floor(63 ** 2 / 4); !$3e0 = $1f
|
|
1440 00ff ld $ff ;$0400 = 1024 = floor(64 ** 2 / 4); !$400 = $ff
|
|
1441 00df ld $df ;$0420 = 1056 = floor(65 ** 2 / 4); !$420 = $df
|
|
1442 00be ld $be ;$0441 = 1089 = floor(66 ** 2 / 4); !$441 = $be
|
|
1443 009d ld $9d ;$0462 = 1122 = floor(67 ** 2 / 4); !$462 = $9d
|
|
1444 007b ld $7b ;$0484 = 1156 = floor(68 ** 2 / 4); !$484 = $7b
|
|
1445 0059 ld $59 ;$04a6 = 1190 = floor(69 ** 2 / 4); !$4a6 = $59
|
|
1446 0036 ld $36 ;$04c9 = 1225 = floor(70 ** 2 / 4); !$4c9 = $36
|
|
1447 0013 ld $13 ;$04ec = 1260 = floor(71 ** 2 / 4); !$4ec = $13
|
|
1448 00ef ld $ef ;$0510 = 1296 = floor(72 ** 2 / 4); !$510 = $ef
|
|
1449 00cb ld $cb ;$0534 = 1332 = floor(73 ** 2 / 4); !$534 = $cb
|
|
144a 00a6 ld $a6 ;$0559 = 1369 = floor(74 ** 2 / 4); !$559 = $a6
|
|
144b 0081 ld $81 ;$057e = 1406 = floor(75 ** 2 / 4); !$57e = $81
|
|
144c 005b ld $5b ;$05a4 = 1444 = floor(76 ** 2 / 4); !$5a4 = $5b
|
|
144d 0035 ld $35 ;$05ca = 1482 = floor(77 ** 2 / 4); !$5ca = $35
|
|
144e 000e ld $0e ;$05f1 = 1521 = floor(78 ** 2 / 4); !$5f1 = $0e
|
|
144f 00e7 ld $e7 ;$0618 = 1560 = floor(79 ** 2 / 4); !$618 = $e7
|
|
1450 00bf ld $bf ;$0640 = 1600 = floor(80 ** 2 / 4); !$640 = $bf
|
|
1451 0097 ld $97 ;$0668 = 1640 = floor(81 ** 2 / 4); !$668 = $97
|
|
1452 006e ld $6e ;$0691 = 1681 = floor(82 ** 2 / 4); !$691 = $6e
|
|
1453 0045 ld $45 ;$06ba = 1722 = floor(83 ** 2 / 4); !$6ba = $45
|
|
1454 001b ld $1b ;$06e4 = 1764 = floor(84 ** 2 / 4); !$6e4 = $1b
|
|
1455 00f1 ld $f1 ;$070e = 1806 = floor(85 ** 2 / 4); !$70e = $f1
|
|
1456 00c6 ld $c6 ;$0739 = 1849 = floor(86 ** 2 / 4); !$739 = $c6
|
|
1457 009b ld $9b ;$0764 = 1892 = floor(87 ** 2 / 4); !$764 = $9b
|
|
1458 006f ld $6f ;$0790 = 1936 = floor(88 ** 2 / 4); !$790 = $6f
|
|
1459 0043 ld $43 ;$07bc = 1980 = floor(89 ** 2 / 4); !$7bc = $43
|
|
145a 0016 ld $16 ;$07e9 = 2025 = floor(90 ** 2 / 4); !$7e9 = $16
|
|
145b 00e9 ld $e9 ;$0816 = 2070 = floor(91 ** 2 / 4); !$816 = $e9
|
|
145c 00bb ld $bb ;$0844 = 2116 = floor(92 ** 2 / 4); !$844 = $bb
|
|
145d 008d ld $8d ;$0872 = 2162 = floor(93 ** 2 / 4); !$872 = $8d
|
|
145e 005e ld $5e ;$08a1 = 2209 = floor(94 ** 2 / 4); !$8a1 = $5e
|
|
145f 002f ld $2f ;$08d0 = 2256 = floor(95 ** 2 / 4); !$8d0 = $2f
|
|
1460 00ff ld $ff ;$0900 = 2304 = floor(96 ** 2 / 4); !$900 = $ff
|
|
1461 00cf ld $cf ;$0930 = 2352 = floor(97 ** 2 / 4); !$930 = $cf
|
|
1462 009e ld $9e ;$0961 = 2401 = floor(98 ** 2 / 4); !$961 = $9e
|
|
1463 006d ld $6d ;$0992 = 2450 = floor(99 ** 2 / 4); !$992 = $6d
|
|
1464 003b ld $3b ;$09c4 = 2500 = floor(100 ** 2 / 4); !$9c4 = $3b
|
|
1465 0009 ld $09 ;$09f6 = 2550 = floor(101 ** 2 / 4); !$9f6 = $09
|
|
1466 00d6 ld $d6 ;$0a29 = 2601 = floor(102 ** 2 / 4); !$a29 = $d6
|
|
1467 00a3 ld $a3 ;$0a5c = 2652 = floor(103 ** 2 / 4); !$a5c = $a3
|
|
1468 006f ld $6f ;$0a90 = 2704 = floor(104 ** 2 / 4); !$a90 = $6f
|
|
1469 003b ld $3b ;$0ac4 = 2756 = floor(105 ** 2 / 4); !$ac4 = $3b
|
|
146a 0006 ld $06 ;$0af9 = 2809 = floor(106 ** 2 / 4); !$af9 = $06
|
|
146b 00d1 ld $d1 ;$0b2e = 2862 = floor(107 ** 2 / 4); !$b2e = $d1
|
|
146c 009b ld $9b ;$0b64 = 2916 = floor(108 ** 2 / 4); !$b64 = $9b
|
|
146d 0065 ld $65 ;$0b9a = 2970 = floor(109 ** 2 / 4); !$b9a = $65
|
|
146e 002e ld $2e ;$0bd1 = 3025 = floor(110 ** 2 / 4); !$bd1 = $2e
|
|
146f 00f7 ld $f7 ;$0c08 = 3080 = floor(111 ** 2 / 4); !$c08 = $f7
|
|
1470 00bf ld $bf ;$0c40 = 3136 = floor(112 ** 2 / 4); !$c40 = $bf
|
|
1471 0087 ld $87 ;$0c78 = 3192 = floor(113 ** 2 / 4); !$c78 = $87
|
|
1472 004e ld $4e ;$0cb1 = 3249 = floor(114 ** 2 / 4); !$cb1 = $4e
|
|
1473 0015 ld $15 ;$0cea = 3306 = floor(115 ** 2 / 4); !$cea = $15
|
|
1474 00db ld $db ;$0d24 = 3364 = floor(116 ** 2 / 4); !$d24 = $db
|
|
1475 00a1 ld $a1 ;$0d5e = 3422 = floor(117 ** 2 / 4); !$d5e = $a1
|
|
1476 0066 ld $66 ;$0d99 = 3481 = floor(118 ** 2 / 4); !$d99 = $66
|
|
1477 002b ld $2b ;$0dd4 = 3540 = floor(119 ** 2 / 4); !$dd4 = $2b
|
|
1478 00ef ld $ef ;$0e10 = 3600 = floor(120 ** 2 / 4); !$e10 = $ef
|
|
1479 00b3 ld $b3 ;$0e4c = 3660 = floor(121 ** 2 / 4); !$e4c = $b3
|
|
147a 0076 ld $76 ;$0e89 = 3721 = floor(122 ** 2 / 4); !$e89 = $76
|
|
147b 0039 ld $39 ;$0ec6 = 3782 = floor(123 ** 2 / 4); !$ec6 = $39
|
|
147c 00fb ld $fb ;$0f04 = 3844 = floor(124 ** 2 / 4); !$f04 = $fb
|
|
147d 00bd ld $bd ;$0f42 = 3906 = floor(125 ** 2 / 4); !$f42 = $bd
|
|
147e 007e ld $7e ;$0f81 = 3969 = floor(126 ** 2 / 4); !$f81 = $7e
|
|
147f 003f ld $3f ;$0fc0 = 4032 = floor(127 ** 2 / 4); !$fc0 = $3f
|
|
1480 00ff ld $ff ;$1000 = 4096 = floor(128 ** 2 / 4); !$1000 = $ff
|
|
1481 00bf ld $bf ;$1040 = 4160 = floor(129 ** 2 / 4); !$1040 = $bf
|
|
1482 007e ld $7e ;$1081 = 4225 = floor(130 ** 2 / 4); !$1081 = $7e
|
|
1483 003d ld $3d ;$10c2 = 4290 = floor(131 ** 2 / 4); !$10c2 = $3d
|
|
1484 00fb ld $fb ;$1104 = 4356 = floor(132 ** 2 / 4); !$1104 = $fb
|
|
1485 00b9 ld $b9 ;$1146 = 4422 = floor(133 ** 2 / 4); !$1146 = $b9
|
|
1486 0076 ld $76 ;$1189 = 4489 = floor(134 ** 2 / 4); !$1189 = $76
|
|
1487 0033 ld $33 ;$11cc = 4556 = floor(135 ** 2 / 4); !$11cc = $33
|
|
1488 00ef ld $ef ;$1210 = 4624 = floor(136 ** 2 / 4); !$1210 = $ef
|
|
1489 00ab ld $ab ;$1254 = 4692 = floor(137 ** 2 / 4); !$1254 = $ab
|
|
148a 0066 ld $66 ;$1299 = 4761 = floor(138 ** 2 / 4); !$1299 = $66
|
|
148b 0021 ld $21 ;$12de = 4830 = floor(139 ** 2 / 4); !$12de = $21
|
|
148c 00db ld $db ;$1324 = 4900 = floor(140 ** 2 / 4); !$1324 = $db
|
|
148d 0095 ld $95 ;$136a = 4970 = floor(141 ** 2 / 4); !$136a = $95
|
|
148e 004e ld $4e ;$13b1 = 5041 = floor(142 ** 2 / 4); !$13b1 = $4e
|
|
148f 0007 ld $07 ;$13f8 = 5112 = floor(143 ** 2 / 4); !$13f8 = $07
|
|
1490 00bf ld $bf ;$1440 = 5184 = floor(144 ** 2 / 4); !$1440 = $bf
|
|
1491 0077 ld $77 ;$1488 = 5256 = floor(145 ** 2 / 4); !$1488 = $77
|
|
1492 002e ld $2e ;$14d1 = 5329 = floor(146 ** 2 / 4); !$14d1 = $2e
|
|
1493 00e5 ld $e5 ;$151a = 5402 = floor(147 ** 2 / 4); !$151a = $e5
|
|
1494 009b ld $9b ;$1564 = 5476 = floor(148 ** 2 / 4); !$1564 = $9b
|
|
1495 0051 ld $51 ;$15ae = 5550 = floor(149 ** 2 / 4); !$15ae = $51
|
|
1496 0006 ld $06 ;$15f9 = 5625 = floor(150 ** 2 / 4); !$15f9 = $06
|
|
1497 00bb ld $bb ;$1644 = 5700 = floor(151 ** 2 / 4); !$1644 = $bb
|
|
1498 006f ld $6f ;$1690 = 5776 = floor(152 ** 2 / 4); !$1690 = $6f
|
|
1499 0023 ld $23 ;$16dc = 5852 = floor(153 ** 2 / 4); !$16dc = $23
|
|
149a 00d6 ld $d6 ;$1729 = 5929 = floor(154 ** 2 / 4); !$1729 = $d6
|
|
149b 0089 ld $89 ;$1776 = 6006 = floor(155 ** 2 / 4); !$1776 = $89
|
|
149c 003b ld $3b ;$17c4 = 6084 = floor(156 ** 2 / 4); !$17c4 = $3b
|
|
149d 00ed ld $ed ;$1812 = 6162 = floor(157 ** 2 / 4); !$1812 = $ed
|
|
149e 009e ld $9e ;$1861 = 6241 = floor(158 ** 2 / 4); !$1861 = $9e
|
|
149f 004f ld $4f ;$18b0 = 6320 = floor(159 ** 2 / 4); !$18b0 = $4f
|
|
14a0 00ff ld $ff ;$1900 = 6400 = floor(160 ** 2 / 4); !$1900 = $ff
|
|
14a1 00af ld $af ;$1950 = 6480 = floor(161 ** 2 / 4); !$1950 = $af
|
|
14a2 005e ld $5e ;$19a1 = 6561 = floor(162 ** 2 / 4); !$19a1 = $5e
|
|
14a3 000d ld $0d ;$19f2 = 6642 = floor(163 ** 2 / 4); !$19f2 = $0d
|
|
14a4 00bb ld $bb ;$1a44 = 6724 = floor(164 ** 2 / 4); !$1a44 = $bb
|
|
14a5 0069 ld $69 ;$1a96 = 6806 = floor(165 ** 2 / 4); !$1a96 = $69
|
|
14a6 0016 ld $16 ;$1ae9 = 6889 = floor(166 ** 2 / 4); !$1ae9 = $16
|
|
14a7 00c3 ld $c3 ;$1b3c = 6972 = floor(167 ** 2 / 4); !$1b3c = $c3
|
|
14a8 006f ld $6f ;$1b90 = 7056 = floor(168 ** 2 / 4); !$1b90 = $6f
|
|
14a9 001b ld $1b ;$1be4 = 7140 = floor(169 ** 2 / 4); !$1be4 = $1b
|
|
14aa 00c6 ld $c6 ;$1c39 = 7225 = floor(170 ** 2 / 4); !$1c39 = $c6
|
|
14ab 0071 ld $71 ;$1c8e = 7310 = floor(171 ** 2 / 4); !$1c8e = $71
|
|
14ac 001b ld $1b ;$1ce4 = 7396 = floor(172 ** 2 / 4); !$1ce4 = $1b
|
|
14ad 00c5 ld $c5 ;$1d3a = 7482 = floor(173 ** 2 / 4); !$1d3a = $c5
|
|
14ae 006e ld $6e ;$1d91 = 7569 = floor(174 ** 2 / 4); !$1d91 = $6e
|
|
14af 0017 ld $17 ;$1de8 = 7656 = floor(175 ** 2 / 4); !$1de8 = $17
|
|
14b0 00bf ld $bf ;$1e40 = 7744 = floor(176 ** 2 / 4); !$1e40 = $bf
|
|
14b1 0067 ld $67 ;$1e98 = 7832 = floor(177 ** 2 / 4); !$1e98 = $67
|
|
14b2 000e ld $0e ;$1ef1 = 7921 = floor(178 ** 2 / 4); !$1ef1 = $0e
|
|
14b3 00b5 ld $b5 ;$1f4a = 8010 = floor(179 ** 2 / 4); !$1f4a = $b5
|
|
14b4 005b ld $5b ;$1fa4 = 8100 = floor(180 ** 2 / 4); !$1fa4 = $5b
|
|
14b5 0001 ld $01 ;$1ffe = 8190 = floor(181 ** 2 / 4); !$1ffe = $01
|
|
14b6 00a6 ld $a6 ;$2059 = 8281 = floor(182 ** 2 / 4); !$2059 = $a6
|
|
14b7 004b ld $4b ;$20b4 = 8372 = floor(183 ** 2 / 4); !$20b4 = $4b
|
|
14b8 00ef ld $ef ;$2110 = 8464 = floor(184 ** 2 / 4); !$2110 = $ef
|
|
14b9 0093 ld $93 ;$216c = 8556 = floor(185 ** 2 / 4); !$216c = $93
|
|
14ba 0036 ld $36 ;$21c9 = 8649 = floor(186 ** 2 / 4); !$21c9 = $36
|
|
14bb 00d9 ld $d9 ;$2226 = 8742 = floor(187 ** 2 / 4); !$2226 = $d9
|
|
14bc 007b ld $7b ;$2284 = 8836 = floor(188 ** 2 / 4); !$2284 = $7b
|
|
14bd 001d ld $1d ;$22e2 = 8930 = floor(189 ** 2 / 4); !$22e2 = $1d
|
|
14be 00be ld $be ;$2341 = 9025 = floor(190 ** 2 / 4); !$2341 = $be
|
|
14bf 005f ld $5f ;$23a0 = 9120 = floor(191 ** 2 / 4); !$23a0 = $5f
|
|
14c0 00ff ld $ff ;$2400 = 9216 = floor(192 ** 2 / 4); !$2400 = $ff
|
|
14c1 009f ld $9f ;$2460 = 9312 = floor(193 ** 2 / 4); !$2460 = $9f
|
|
14c2 003e ld $3e ;$24c1 = 9409 = floor(194 ** 2 / 4); !$24c1 = $3e
|
|
14c3 00dd ld $dd ;$2522 = 9506 = floor(195 ** 2 / 4); !$2522 = $dd
|
|
14c4 007b ld $7b ;$2584 = 9604 = floor(196 ** 2 / 4); !$2584 = $7b
|
|
14c5 0019 ld $19 ;$25e6 = 9702 = floor(197 ** 2 / 4); !$25e6 = $19
|
|
14c6 00b6 ld $b6 ;$2649 = 9801 = floor(198 ** 2 / 4); !$2649 = $b6
|
|
14c7 0053 ld $53 ;$26ac = 9900 = floor(199 ** 2 / 4); !$26ac = $53
|
|
14c8 00ef ld $ef ;$2710 = 10000 = floor(200 ** 2 / 4); !$2710 = $ef
|
|
14c9 008b ld $8b ;$2774 = 10100 = floor(201 ** 2 / 4); !$2774 = $8b
|
|
14ca 0026 ld $26 ;$27d9 = 10201 = floor(202 ** 2 / 4); !$27d9 = $26
|
|
14cb 00c1 ld $c1 ;$283e = 10302 = floor(203 ** 2 / 4); !$283e = $c1
|
|
14cc 005b ld $5b ;$28a4 = 10404 = floor(204 ** 2 / 4); !$28a4 = $5b
|
|
14cd 00f5 ld $f5 ;$290a = 10506 = floor(205 ** 2 / 4); !$290a = $f5
|
|
14ce 008e ld $8e ;$2971 = 10609 = floor(206 ** 2 / 4); !$2971 = $8e
|
|
14cf 0027 ld $27 ;$29d8 = 10712 = floor(207 ** 2 / 4); !$29d8 = $27
|
|
14d0 00bf ld $bf ;$2a40 = 10816 = floor(208 ** 2 / 4); !$2a40 = $bf
|
|
14d1 0057 ld $57 ;$2aa8 = 10920 = floor(209 ** 2 / 4); !$2aa8 = $57
|
|
14d2 00ee ld $ee ;$2b11 = 11025 = floor(210 ** 2 / 4); !$2b11 = $ee
|
|
14d3 0085 ld $85 ;$2b7a = 11130 = floor(211 ** 2 / 4); !$2b7a = $85
|
|
14d4 001b ld $1b ;$2be4 = 11236 = floor(212 ** 2 / 4); !$2be4 = $1b
|
|
14d5 00b1 ld $b1 ;$2c4e = 11342 = floor(213 ** 2 / 4); !$2c4e = $b1
|
|
14d6 0046 ld $46 ;$2cb9 = 11449 = floor(214 ** 2 / 4); !$2cb9 = $46
|
|
14d7 00db ld $db ;$2d24 = 11556 = floor(215 ** 2 / 4); !$2d24 = $db
|
|
14d8 006f ld $6f ;$2d90 = 11664 = floor(216 ** 2 / 4); !$2d90 = $6f
|
|
14d9 0003 ld $03 ;$2dfc = 11772 = floor(217 ** 2 / 4); !$2dfc = $03
|
|
14da 0096 ld $96 ;$2e69 = 11881 = floor(218 ** 2 / 4); !$2e69 = $96
|
|
14db 0029 ld $29 ;$2ed6 = 11990 = floor(219 ** 2 / 4); !$2ed6 = $29
|
|
14dc 00bb ld $bb ;$2f44 = 12100 = floor(220 ** 2 / 4); !$2f44 = $bb
|
|
14dd 004d ld $4d ;$2fb2 = 12210 = floor(221 ** 2 / 4); !$2fb2 = $4d
|
|
14de 00de ld $de ;$3021 = 12321 = floor(222 ** 2 / 4); !$3021 = $de
|
|
14df 006f ld $6f ;$3090 = 12432 = floor(223 ** 2 / 4); !$3090 = $6f
|
|
14e0 00ff ld $ff ;$3100 = 12544 = floor(224 ** 2 / 4); !$3100 = $ff
|
|
14e1 008f ld $8f ;$3170 = 12656 = floor(225 ** 2 / 4); !$3170 = $8f
|
|
14e2 001e ld $1e ;$31e1 = 12769 = floor(226 ** 2 / 4); !$31e1 = $1e
|
|
14e3 00ad ld $ad ;$3252 = 12882 = floor(227 ** 2 / 4); !$3252 = $ad
|
|
14e4 003b ld $3b ;$32c4 = 12996 = floor(228 ** 2 / 4); !$32c4 = $3b
|
|
14e5 00c9 ld $c9 ;$3336 = 13110 = floor(229 ** 2 / 4); !$3336 = $c9
|
|
14e6 0056 ld $56 ;$33a9 = 13225 = floor(230 ** 2 / 4); !$33a9 = $56
|
|
14e7 00e3 ld $e3 ;$341c = 13340 = floor(231 ** 2 / 4); !$341c = $e3
|
|
14e8 006f ld $6f ;$3490 = 13456 = floor(232 ** 2 / 4); !$3490 = $6f
|
|
14e9 00fb ld $fb ;$3504 = 13572 = floor(233 ** 2 / 4); !$3504 = $fb
|
|
14ea 0086 ld $86 ;$3579 = 13689 = floor(234 ** 2 / 4); !$3579 = $86
|
|
14eb 0011 ld $11 ;$35ee = 13806 = floor(235 ** 2 / 4); !$35ee = $11
|
|
14ec 009b ld $9b ;$3664 = 13924 = floor(236 ** 2 / 4); !$3664 = $9b
|
|
14ed 0025 ld $25 ;$36da = 14042 = floor(237 ** 2 / 4); !$36da = $25
|
|
14ee 00ae ld $ae ;$3751 = 14161 = floor(238 ** 2 / 4); !$3751 = $ae
|
|
14ef 0037 ld $37 ;$37c8 = 14280 = floor(239 ** 2 / 4); !$37c8 = $37
|
|
14f0 00bf ld $bf ;$3840 = 14400 = floor(240 ** 2 / 4); !$3840 = $bf
|
|
14f1 0047 ld $47 ;$38b8 = 14520 = floor(241 ** 2 / 4); !$38b8 = $47
|
|
14f2 00ce ld $ce ;$3931 = 14641 = floor(242 ** 2 / 4); !$3931 = $ce
|
|
14f3 0055 ld $55 ;$39aa = 14762 = floor(243 ** 2 / 4); !$39aa = $55
|
|
14f4 00db ld $db ;$3a24 = 14884 = floor(244 ** 2 / 4); !$3a24 = $db
|
|
14f5 0061 ld $61 ;$3a9e = 15006 = floor(245 ** 2 / 4); !$3a9e = $61
|
|
14f6 00e6 ld $e6 ;$3b19 = 15129 = floor(246 ** 2 / 4); !$3b19 = $e6
|
|
14f7 006b ld $6b ;$3b94 = 15252 = floor(247 ** 2 / 4); !$3b94 = $6b
|
|
14f8 00ef ld $ef ;$3c10 = 15376 = floor(248 ** 2 / 4); !$3c10 = $ef
|
|
14f9 0073 ld $73 ;$3c8c = 15500 = floor(249 ** 2 / 4); !$3c8c = $73
|
|
14fa 00f6 ld $f6 ;$3d09 = 15625 = floor(250 ** 2 / 4); !$3d09 = $f6
|
|
14fb 0079 ld $79 ;$3d86 = 15750 = floor(251 ** 2 / 4); !$3d86 = $79
|
|
14fc 00fb ld $fb ;$3e04 = 15876 = floor(252 ** 2 / 4); !$3e04 = $fb
|
|
14fd 007d ld $7d ;$3e82 = 16002 = floor(253 ** 2 / 4); !$3e82 = $7d
|
|
14fe 00fe ld $fe ;$3f01 = 16129 = floor(254 ** 2 / 4); !$3f01 = $fe
|
|
14ff 007f ld $7f ;$3f80 = 16256 = floor(255 ** 2 / 4); !$3f80 = $7f
|
|
5429 C(f"${val:04x} = {val} = floor({i} ** 2 / 4); !${val:02x} = ${(~val) & 0xff:02x}")
|
|
5430 align(0x100)
|
|
5431
|
|
5432
|
|
5433 label("sys_MultiplyBytes#44")
|
|
sys_MultiplyBytes#44:
|
|
1500 c218 st [$18] 5434 st([vAC]) #44
|
|
1501 00fb ld $fb 5435 ld("sys_MultiplyBytes.high-byte-action.restore-and-add") #45
|
|
1502 c228 st [$28] 5436 st([sysArgs + 4]) #46
|
|
1503 0008 ld $08 5437 ld("sys_MultiplyBytes#68") #47
|
|
1504 c229 st [$29] 5438 st([sysArgs + 5]) #48
|
|
1505 0126 ld [$26] 5439 ld([sysArgs + 2]) #49
|
|
1506 e0f3 jmp y,$f3 5440 jmp(Y, "sys_MultiplyBytes.tableEntry") #50
|
|
1507 8127 adda [$27] 5441 adda([sysArgs + 3]) #51
|
|
5442 label("sys_MultiplyBytes#68")
|
|
sys_MultiplyBytes#68:
|
|
1508 60ff xora $ff 5443 xora(0xff) #68
|
|
1509 8001 adda $01 5444 adda(1) #69
|
|
150a 8118 adda [$18] 5445 adda([vAC]) #70
|
|
150b c21d st [$1d] 5446 st([vTmp]) #71
|
|
150c e810 blt $1510 5447 blt(pc() + 4) #72
|
|
150d a118 suba [$18] 5448 suba([vAC]) #73
|
|
150e fc12 bra $1512 5449 bra(pc() + 4) #74
|
|
150f 4118 ora [$18] 5450 ora([vAC]) #75
|
|
1510 fc12 bra $1512 5451 bra(pc() + 2) #74
|
|
1511 2118 anda [$18] 5452 anda([vAC]) #75
|
|
1512 3080 anda $80,x 5453 anda(0b1000_0000, X) #76
|
|
1513 011d ld [$1d] 5454 ld([vTmp]) #77
|
|
1514 c218 st [$18] 5455 st([vAC]) #78
|
|
1515 0500 ld [x] 5456 ld([X]) #79
|
|
1516 8119 adda [$19] 5457 adda([vAC + 1]) #80
|
|
1517 c219 st [$19] 5458 st([vAC + 1]) #81
|
|
5459 # 7 bit x 7 bit multiply complete
|
|
1518 0124 ld [$24] 5460 ld([sysArgs + 0]) #82
|
|
1519 6125 xora [$25] 5461 xora([sysArgs + 1]) #83
|
|
5462 blt("sys_MultiplyBytes.oneMsbSetCase") # 84
|
|
151a e839 blt sys_MultiplyBytes.oneMsbSetCase
|
|
151b 0124 ld [$24] 5463 ld([sysArgs + 0]) #85
|
|
151c e821 blt $1521 5464 blt(pc() + 5) #86
|
|
151d 0040 ld $40 5465 ld(2 ** 14 >> 8) #87
|
|
151e 1403 ld $03,y 5466 ld(hi('NEXTY'), Y) #88
|
|
151f e000 jmp y,$00 5467 jmp(Y, 'NEXTY') #89
|
|
1520 00d2 ld $d2 5468 ld(-92/2) #90
|
|
5469
|
|
1521 8119 adda [$19] 5470 adda([vAC + 1]) #88
|
|
1522 c219 st [$19] 5471 st([vAC + 1]) #89
|
|
1523 0126 ld [$26] 5472 ld([sysArgs + 2]) #90
|
|
1524 8127 adda [$27] 5473 adda([sysArgs + 3]) #91
|
|
5474 label("sys_MultiplyBytes#92")
|
|
5475 # Reusing sysArgs + 2, because we can't use vTmp twice
|
|
sys_MultiplyBytes#92:
|
|
1525 c226 st [$26] 5476 st([sysArgs + 2]) #92
|
|
1526 2001 anda $01 5477 anda(0b0000_0001) #93
|
|
1527 807f adda $7f 5478 adda(0b0111_1111) #94
|
|
1528 2080 anda $80 5479 anda(0b1000_0000) #95
|
|
1529 1200 ld ac,x 5480 ld(AC, X) #96
|
|
152a 8118 adda [$18] 5481 adda([vAC]) #97
|
|
152b c218 st [$18] 5482 st([vAC]) #98
|
|
152c e82f blt $152f 5483 blt(pc() + 3) #99
|
|
152d fc30 bra $1530 5484 bra(pc() + 3) #100
|
|
152e 0500 ld [x] 5485 ld([X]) #101
|
|
152f 0000 ld $00 5486 ld(0) #101
|
|
1530 8119 adda [$19] 5487 adda([vAC + 1]) #102
|
|
1531 c219 st [$19] 5488 st([vAC + 1]) #103
|
|
1532 00f6 ld $f6 5489 ld("sys_MultiplyBytes#114") #104
|
|
1533 c21d st [$1d] 5490 st([vTmp]) #105
|
|
1534 0126 ld [$26] 5491 ld([sysArgs + 2]) #106
|
|
1535 20fe anda $fe 5492 anda(0b1111_1110) #107
|
|
1536 1405 ld $05,y 5493 ld(hi("shiftTable"), Y) #108
|
|
1537 e200 jmp y,ac 5494 jmp(Y, AC) #109
|
|
1538 fcff bra $ff 5495 bra(0xFF) #110
|
|
5496 # The rest happens in and after the shift table,
|
|
5497 # but to save you looking it, looks like this
|
|
5498 #111 ld (ac >> 1)
|
|
5499 #112 bra [vTmp]
|
|
5500 #113 nop
|
|
5501 #114 adda [vAC + 1]
|
|
5502 #115 st [vAC + 1]
|
|
5503 #116 ld hi('NEXTY'), y
|
|
5504 #117 jmp y, 'NEXTY'
|
|
5505 #118 ld -120/2
|
|
5506 label("sys_MultiplyBytes.oneMsbSetCase")
|
|
sys_MultiplyBytes.oneMsbSetCase:
|
|
1539 f43c bge $153c 5507 bge(pc() + 3) # 86
|
|
153a fc3d bra $153d 5508 bra(pc() + 3) # 87
|
|
153b 0127 ld [$27] 5509 ld([sysArgs + 3]) # 88
|
|
153c 0126 ld [$26] 5510 ld([sysArgs + 2]) # 88
|
|
153d 0200 nop 5511 nop() # 89
|
|
5512 bra("sys_MultiplyBytes#92") # 90
|
|
153e fc25 bra sys_MultiplyBytes#92
|
|
153f 0200 nop 5513 nop() # 91
|
|
5514
|
|
5515
|
|
5516 label("SYS_KaratsubaPrepare_54")
|
|
5517 # Prepare arguments for SYS_MultiplyBytes.
|
|
5518 # Arguments are in sysArgs[0:1] and vAC[0:1]
|
|
5519 # Result goes in sysArgs[0:1], and vAC contains zero if the result is going to be positive
|
|
5520 #
|
|
5521 # First calculate abs(sysArgs[0] - sysArgs[1]), remembering whether we had to negate.
|
|
SYS_KaratsubaPrepare_54:
|
|
1540 0124 ld [$24] 5522 ld([sysArgs]) # 15
|
|
5523 bmi("sysKaratsubaPrepare#18") # 16
|
|
1541 e846 blt sysKaratsubaPrepare#18
|
|
1542 a125 suba [$25] 5524 suba([sysArgs + 1]) # 17
|
|
5525
|
|
1543 c224 st [$24] 5526 st([sysArgs]) # 18
|
|
5527 bra("sysKaratsubaPrepare#21") # 19
|
|
1544 fc49 bra sysKaratsubaPrepare#21
|
|
1545 4125 ora [$25] 5528 ora([sysArgs + 1]) # 20
|
|
5529
|
|
5530 label("sysKaratsubaPrepare#18")
|
|
sysKaratsubaPrepare#18:
|
|
1546 c224 st [$24] 5531 st([sysArgs]) # 18
|
|
1547 2125 anda [$25] 5532 anda([sysArgs + 1]) # 19
|
|
1548 0200 nop 5533 nop() # 20
|
|
5534
|
|
5535 label("sysKaratsubaPrepare#21")
|
|
sysKaratsubaPrepare#21:
|
|
1549 3080 anda $80,x 5536 anda(0x80,X) # 21 Store sign for later
|
|
154a e84e blt $154e 5537 bmi(pc()+4) # 22 Invert if necessary
|
|
154b 0124 ld [$24] 5538 ld([sysArgs]) # 23
|
|
5539
|
|
154c fc50 bra $1550 5540 bra(pc() + 4) # 24 No need to negate
|
|
154d 0200 nop 5541 nop() # 25
|
|
5542
|
|
154e 60ff xora $ff 5543 xora(0xff) # 24 Need to negate
|
|
154f 8001 adda $01 5544 adda(1) # 25
|
|
5545
|
|
1550 c224 st [$24] 5546 st([sysArgs]) # 26
|
|
1551 0500 ld [x] 5547 ld([X]) # 27 Store sign
|
|
1552 c21d st [$1d] 5548 st([vTmp]) # 28
|
|
5549
|
|
5550 # Same dance, a second time, but for the other value
|
|
1553 0119 ld [$19] 5551 ld([vAC + 1]) # 29
|
|
5552 bmi("sysKaratsubaPrepare#32") # 30
|
|
1554 e859 blt sysKaratsubaPrepare#32
|
|
1555 a118 suba [$18] 5553 suba([vAC]) # 31
|
|
5554
|
|
1556 c225 st [$25] 5555 st([sysArgs + 1]) # 32
|
|
5556 bra("sysKaratsubaPrepare#35") # 33
|
|
1557 fc5c bra sysKaratsubaPrepare#35
|
|
1558 4118 ora [$18] 5557 ora([vAC]) # 34
|
|
5558
|
|
5559 label("sysKaratsubaPrepare#32")
|
|
sysKaratsubaPrepare#32:
|
|
1559 c225 st [$25] 5560 st([sysArgs + 1]) # 32
|
|
155a 2118 anda [$18] 5561 anda([vAC]) # 33
|
|
155b 0200 nop 5562 nop() # 34
|
|
5563
|
|
5564 label("sysKaratsubaPrepare#35")
|
|
sysKaratsubaPrepare#35:
|
|
155c 3080 anda $80,x 5565 anda(0x80,X) # 35 Store sign for later
|
|
155d e861 blt $1561 5566 bmi(pc()+4) # 36 Invert if necessary
|
|
155e 0125 ld [$25] 5567 ld([sysArgs + 1]) # 37
|
|
5568
|
|
155f fc63 bra $1563 5569 bra(pc() + 4) # 38
|
|
1560 0200 nop 5570 nop() # 39
|
|
5571
|
|
1561 60ff xora $ff 5572 xora(0xff) # 38
|
|
1562 8001 adda $01 5573 adda(1) # 39
|
|
5574
|
|
1563 c225 st [$25] 5575 st([sysArgs + 1]) # 40
|
|
5576
|
|
5577 # Store flag to say if result must be inverted
|
|
1564 011d ld [$1d] 5578 ld([vTmp]) # 41
|
|
1565 6500 xora [x] 5579 xora([X]) # 42
|
|
1566 c218 st [$18] 5580 st([vAC]) # 43
|
|
1567 c219 st [$19] 5581 st([vAC + 1]) # 44
|
|
5582
|
|
1568 0013 ld $13 5583 ld(hi("SYS_MultiplyBytes_120")) # 45
|
|
1569 c223 st [$23] 5584 st([sysFn + 1]) # 46
|
|
156a 00e3 ld $e3 5585 ld("SYS_MultiplyBytes_120") # 47
|
|
156b c222 st [$22] 5586 st([sysFn]) # 48
|
|
156c 1403 ld $03,y 5587 ld(hi('REENTER'), Y) # 49
|
|
156d e0cb jmp y,$cb 5588 jmp(Y, 'REENTER') # 50
|
|
156e 00e5 ld $e5 5589 ld(-54/2) # 51
|
|
5590
|
|
5591
|
|
5592
|
|
5593
|
|
5594 #-----------------------------------------------------------------------
|
|
5595 #
|
|
5596 # End of core
|
|
5597 #
|
|
5598 #-----------------------------------------------------------------------
|
|
5599 if __name__ == '__main__': disableListing()
|
|
sys_ReadRomDir:
|
|
156f f075 beq .sysDir#20
|
|
1570 1024 ld $24,x
|
|
1571 1600 ld ac,y
|
|
1572 0118 ld [$18]
|
|
1573 a00e suba $0e
|
|
1574 e200 jmp y,ac
|
|
.sysDir#20: 1575 1400 ld $00,y
|
|
1576 007a ld $7a
|
|
1577 1415 ld $15,y
|
|
1578 e200 jmp y,ac
|
|
1579 1400 ld $00,y
|
|
.sysDir#25:
|
|
.sysDir#39: 157a 1403 ld $03,y
|
|
157b e0cb jmp y,$cb
|
|
157c 00ea ld $ea
|
|
157d 0200 nop ;126 fillers
|
|
157e 0200 nop
|
|
157f 0200 nop
|
|
* 126 times
|
|
15fb fe00 bra ac ;+-----------------------------------+
|
|
15fc fcfd bra $15fd ;| |
|
|
15fd 1404 ld $04,y ;| Trampoline for page $1500 lookups |
|
|
15fe e068 jmp y,$68 ;| |
|
|
15ff c218 st [$18] ;+-----------------------------------+
|
|
1600
|