started on the cade that is astro

This commit is contained in:
Steven Hugg 2018-08-28 18:11:22 -04:00
parent 59469b41b8
commit 9e900a5a26
13 changed files with 1289 additions and 21 deletions

View File

@ -57,6 +57,7 @@ TODO:
- stop debugging where mouse clicked
- bring back the profiler!
- vcs disasm is broken
- links to external tools in ide
On the website the additional grey spacing next to the program line numbers is not dynamically resized when the web browser window size is changed. Intentional?

View File

@ -318,6 +318,8 @@ function require(modname) {
<script src="gen/ui.js"></script>
<!-- <script src="src/audio/votrax.js"></script> -->
<script src="local/lzg.js"></script>
<script>
startUI(true);
</script>

View File

@ -0,0 +1,35 @@
; Demo 1: HELLO, WORLDS! / 2018 hxlnt
; Inspired by Adam Trionfo's Hello World
; http://www.ballyalley.com/ml/ml_homebrew/helloworld/hello.asm
; Assemble with Zmac 1.3
; From: https://github.com/hxlnt/astrocade
INCLUDE "hvglib.h" ; Include HVGLIB library
ORG FIRSTC ; Initialize at beginning of cartridge ROM area
DB $55 ; ... with the code for a normal menued cartridge
DW MENUST ; Initialize menu
DW PrgName ; ... with string at PrgName
DW PrgStart ; ... such that selecting the program enters PrgStart
PrgName: DB "HELLO, WORLDS!"; String
DB 0 ; ... which must be followed by 0
PrgStart: DI ; Disable interrupts
SYSTEM INTPC ; Begin interpreter mode
DO SETOUT ; Set output ports
DB 100*2 ; ... with VBLANK line set to line 100
DB 112/4 ; ... with color boundary 112 pixels from the left of the screen
DB 00001000b ; ... with screen interrupts reenabled
DO COLSET ; Set color palettes
DW Palettes ; ... with the values at Palettes
DO FILL ; Set background fill
DW NORMEM ; ... starting at the beginning of screen RAM
DW 100*BYTEPL ; ... and going for 100 lines
DB 00010010b ; ... with a fill pattern of three different colored pixels
DO STRDIS ; Set string display
DB 0 ; ... starting 0 pixels from the left of the screen
DB 32 ; ... and 32 pixels from the top of the screen
DB 00001100b ; ... with no enlargement, foreground color = 11, background color = 00
DW PrgName ; ... to show string at PrgName
; EXIT ; Exit interpreter mode
Loop: JP Loop ; Play infinite loop
Palettes: DB $BF,$00,$00,$00 ; Left color palette (11b, 10b, 01b, 00b)
DB $E7,$9A,$39,$19 ; Right color palette (11b, 10b, 01b, 00b)

View File

@ -0,0 +1,52 @@
; Telephone
; Inspired by Adam Trionfo's Happy Birthday Music
; http://ballyalley.com/ml/ml_homebrew/birthday.asm
; Assemble with Zmac 1.3
; From: https://github.com/hxlnt/astrocade
INCLUDE "hvglib.h" ; Include HVGLIB library
MUSICSP = $4FD2 ; Music stack pointer
ORG FIRSTC ; Initialize at beginning of cartridge ROM area
DB $55 ; ... with the code for a normal menued cartridge
DW MENUST ; Initialize menu
DW PrgName ; ... with string at PrgName
DW PrgStart ; ... such that selecting the program enters PrgStart
PrgName: DB "TELEPHONE" ; String to be displayed on menu
DB 0 ; ... which must be followed by 0
PrgStart: DI ; Disable interrupts
SYSTEM INTPC ; Begin interpreter mode
DO SETOUT ; Set output ports
DB 80*2 ; ... with VBLANK line set to line 80
DB 44/4 ; ... with color boundary 44 pixels from the left of the screen
DB 00001000b ; ... with screen interrupts reenabled
DO COLSET ; Set color palettes
DW Palettes ; ... with the values at Palettes
DO FILL ; Fill screen
DW NORMEM ; ... starting at the beginning of screen RAM
DW 81*BYTEPL ; ... and going for 81 lines
DB 00000000b ; ... with a solid black (color 0) fill pattern
DO MOVE ; Display graphic
DW NORMEM+(38*BYTEPL)
DW 20*BYTEPL ; ... copy 20 lines
DW Telephone ; ... from data at location Telephone
DO ACTINT ; Activate subtimer interrupts
DO BMUSIC ; Play music
DW MUSICSP ; ... using predefined music stack address
DB 00110011B ; ... setting tone B, vibrato, noise bits
DW Ringing ; ... with music score defined at Ringing
EXIT ; Exit interpreter mode
Loop: JP Loop ; Play infinite loop
Palettes: DB $07,$FE,$FB,$00 ; Left color palette (11b, 10b, 01b, 00b)
DB $07,$4F,$CB,$00 ; Right color palette (11b, 10b, 01b, 00b)
Telephone: ; Telephone graphic
INCLUDE "02-telephone.gfx"
Ringing: ; Music score
MASTER OA3 ;
VOLUME $80, $00 ;
NOTE1 60, C4 ; ... in which notes oscillate between C4
NOTE1 60, F4 ; ... and F4
REST 80 ; ... followed by a short rest
NOTE1 60, C4 ; ... then another ring
NOTE1 60, F4 ;
REST 160 ; ... and a long rest
JP Ringing ; ... ending in replay

View File

@ -0,0 +1,26 @@
DB $0, $0, $0, $0, $0, $0, $0, $33, $0, $FF, $0, $EE, $0, $EE, $0, $AA, $0, $AA, $0, $AA, $0, $AA, $0, $AA, $0, $BB, $0, $BB, $0, $FF, $0, $CC, $0, $0, $0, $0, $0, $0, $0, $0
DB $0, $0, $0, $0, $0, $0, $0, $0, $33, $0, $FF, $0, $EE, $0, $AA, $0, $AA, $0, $AA, $0, $AA, $0, $AA, $0, $AA, $0, $BB, $0, $FF, $0, $CC, $0, $0, $0, $0, $0, $0, $0, $0, $0
DB $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0
DB $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0
DB $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0
DB $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0
DB $0, $0, $0, $0, $0, $0, $0, $0, $FF, $D0, $0, $03, $FF, $FD, $3F, $FD, $0F, $0, $03, $FF, $D0, $FF, $40, $3C, $0F, $0F, $FD, $03, $FF, $40, $FF, $F4, $0, $0, $0, $0, $0, $0, $0, $0
DB $0, $0, $0, $0, $0, $0, $0, $0F, $55, $55, $0, $03, $55, $54, $D5, $55, $35, $0, $0D, $55, $53, $55, $50, $D4, $35, $35, $55, $4D, $55, $53, $55, $54, $0, $0, $0, $0, $0, $0, $0, $0
DB $0, $0, $0, $0, $0, $0, $0, $1D, $55, $55, $40, $0, $05, $40, $D4, $0, $35, $0, $0D, $40, $03, $50, $54, $D4, $35, $35, $05, $4D, $41, $53, $50, $0, $0, $0, $0, $0, $0, $0, $0, $0
DB $0, $0, $0, $0, $0, $0, $0, $55, $20, $85, $54, $0, $05, $40, $54, $0, $15, $0, $05, $40, $01, $50, $14, $54, $15, $15, $05, $45, $41, $51, $50, $0, $0, $0, $0, $0, $0, $0, $0, $0
DB $0, $0, $0, $0, $0, $0, $0, $55, $AA, $A5, $5C, $0, $05, $40, $54, $0, $15, $0, $05, $40, $01, $50, $54, $54, $15, $15, $05, $45, $41, $51, $50, $0, $0, $0, $0, $0, $0, $0, $0, $0
DB $0, $0, $0, $0, $0, $0, $0, $16, $AA, $A9, $45, $0, $05, $40, $57, $FD, $15, $0, $05, $7F, $D1, $5F, $50, $57, $D5, $15, $05, $45, $41, $51, $5F, $F4, $0, $0, $0, $0, $0, $0, $0, $0
DB $0, $0, $0, $0, $0, $0, $0, $0A, $77, $6A, $02, $C0, $05, $40, $55, $55, $15, $0, $05, $55, $51, $55, $40, $55, $55, $15, $05, $45, $41, $51, $55, $54, $0, $0, $0, $0, $0, $0, $0, $0
DB $0, $0, $0, $0, $0, $0, $0, $0A, $EE, $EA, $01, $0, $05, $40, $54, $0, $15, $0, $05, $40, $01, $50, $0, $54, $15, $15, $05, $45, $41, $51, $50, $0, $0, $0, $0, $0, $0, $0, $0, $0
DB $0, $0, $0, $0, $0, $0, $0, $2A, $77, $6A, $8B, $0, $05, $40, $54, $0, $15, $0, $05, $40, $01, $50, $0, $54, $15, $15, $05, $45, $41, $51, $50, $0, $0, $0, $0, $0, $0, $0, $0, $0
DB $0, $0, $0, $0, $0, $0, $0, $2A, $EE, $EA, $85, $0, $05, $40, $54, $0, $15, $0, $05, $40, $01, $50, $0, $54, $15, $15, $05, $45, $41, $51, $50, $0, $0, $0, $0, $0, $0, $0, $0, $0
DB $0, $0, $0, $0, $0, $0, $0, $2A, $AA, $AA, $8B, $0, $05, $40, $57, $FD, $15, $FF, $45, $7F
DB $D1, $50, $0, $54, $15, $15, $F5, $45, $41, $51, $5F, $F4, $0, $0, $0, $0, $0, $0, $0, $0
DB $0, $0, $0, $0, $0, $0, $0, $05, $55, $55, $14, $0, $01, $40, $15, $55, $05, $55, $41, $55
DB $51, $50, $0, $14, $05, $05, $55, $01, $40, $50, $55, $54, $0, $0, $0, $0, $0, $0, $0, $0
DB $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0
DB $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0
DB $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0
DB $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0, $0
DB $0, $0, $0, $0, $0, $0, $0, $0, $33, $0, $FF, $0, $EE, $0, $AA, $0, $AA, $0, $AA, $0, $AA, $0, $AA, $0, $AA, $0, $BB, $0, $FF, $0, $CC, $0, $0, $0, $0, $0, $0, $0, $0, $0
DB $0, $0, $0, $0, $0, $0, $0, $33, $0, $FF, $0, $EE, $0, $EE, $0, $AA, $0, $AA, $0, $AA, $0, $AA, $0, $AA, $0, $BB, $0, $BB, $0, $FF, $0, $CC, $0, $0, $0, $0, $0, $0, $0, $0

View File

@ -0,0 +1,88 @@
; "HORCB Pal" demo 2018 hxlnt
; Inspired by Michael Garber's Color Picker
; http://ballyalley.com/ml/ml_homebrew/colorpicker.asm
; Assemble with Zmac 1.3
; From: https://github.com/hxlnt/astrocade
INCLUDE "hvglib.h" ; Include HVGLIB library
FrameCount EQU $4F00 ; Reserve a space for a frame counter
ORG FIRSTC ; Initialize at beginning of cartridge ROM area
DB $55 ; ... with the code for a normal menued cartridge
DW MENUST ; Initialize menu
DW PrgName ; ... with string at PrgName
DW PrgStart ; ... such that selecting the program enters PrgStart
PrgName: DB "HORCB PAL" ; String
DB 0 ; ... which must be followed by 0
PrgStart: DI ; Disable interrupts
SYSTEM INTPC ; Begin interpreter mode
DO SETOUT ; Set output ports
DB 96*2 ; ... with VBLANK line set to line 96
DB 0/4 ; ... with color boundary 0 pixels from the left of the screen
DB 00001000b ; ... with screen interrupts enabled
DO COLSET ; Set color palettes
DW Palettes ; ... with the values at Palettes
DO FILL ; Set background fill
DW NORMEM ; ... starting at the beginning of screen RAM
DW 24*BYTEPL ; ... and going for 24 lines
DB 00011011b ; ... with a fill pattern of four different colored pixels
DO FILL ; Set background fill
DW NORMEM+(24*BYTEPL)
DW 24*BYTEPL ; ... and going for 24 lines
DB 00000000b ; ... with a solid fill of color 00
DO FILL ; Set background fill
DW NORMEM+(48*BYTEPL)
DW 24*BYTEPL ; ... and going for 24 lines
DB 11111111b ; ... with a solid fill of color 11
DO STRDIS ; Set string display
DB 28 ; ... starting 28 pixels from the left of the screen
DB 40 ; ... and 40 pixels from the top of the screen
DB 00001100b ; ... with no enlargement, foreground color = 11, background color = 00
DW PrgName ; ... with string at PrgName
EXIT ; Exit interpreter mode
Loop: IN A,(POT0) ; Let A = controller 1 knob value
OUT (HORCB),A ; Let horizontal color boundary = A
CALL UpdateDisp ; Call UpdateDisp subroutine
JP Loop ; Go back to beginning of infinite loop
Palettes: DB $F4,$1C,$1F,$5F ; Left color palette (11b, 10b, 01b, 00b)
DB $ED,$CD,$D5,$8E ; Right color palette (11b, 10b, 01b, 00b)
UpdateDisp: DI ; Disable interrupts
PUSH AF ; Push AF to SP
LD C,A ; Get first hex digit from knob value
SRL C ; ...
SRL C ; ...
SRL C ; ...
SRL C ; ...
LD B,0 ; Display first hex digit from knob value
LD HL,Hex ; ... Load HL with address Hex
ADD HL,BC ; ... Offset Hex by BC to get first hex digit
LD A,(HL) ; ... Load A with first hex digit
LD C,00000100b ; ... Load C with string options
LD D,40 ; ... Load D with string Y-coordinate
LD E,120 ; ... Load E with X-coordinate
SYSTEM (CHRDIS) ; ... Display first digit
POP AF ; Pop AF off SP
AND $0F ; Get second hex digit from knob value
LD C,A ; ...
LD B,0 ; Display second hex digit from knob value
LD HL,Hex ; ... Load HL with address Hex
ADD HL,BC ; ... Offset Hex by BC to get second hex digit
LD A,(HL) ; ... Load A with second hex digit
LD C,00000100b ; ... Load C with string options
LD D,40 ; ... Load D with Y-coordinate
LD E,128 ; ... Load E with X-coordinate
SYSTEM (CHRDIS) ; ... Display second digit
LD A,(FrameCount) ; Increment frame counter
INC A ; ...
LD (FrameCount),A ; ...
AND 00000111b ; Every fourth frame, run AnimBars
CP 00000100b ; ...
JR Z, AnimBars ; ...
JP AnimDone ; Otherwise, skip AnimBars
AnimBars: SYSSUK RANGED ; Load a random 8-bit number in A
DEFB 0 ; ...
LD BC,24*BYTEPL ; Load BC with one scanline's length
LD DE,NORMEM+(72*BYTEPL)
SYSTEM FILL ; Fill remainder of screen with repeating random tile
AnimDone: EI ; Enable interrupts
RET ; Return from subroutine
Hex: DB "0123456789ABCDEF"

683
presets/astrocade/hvglib.h Normal file
View File

@ -0,0 +1,683 @@
; ****** HVGLIB.H (formally called ballyequ.h) (C)1977,78
; *** Bally Astrocade Equates and Macros Header File ***
; From the nutting_manual and reformatted using Mixed Case
; Version 3.01 - thru December 29, 2010
; by Richard C Degler, from scratch
;
; > Retyped and proofread by Adam Trionfo and Lance F. Squire
; > Version 1.0 (as ballyequ.h) - January 17, 2002
; > Version 2.52 (Version 1.0 of HVGLIB.H) - March 28, 2003
; > Version 2.6 - March 2, 2004 - as seen on BallyAlley.com
; > Version 3.0 - 2009
; > Version 3.01 - Changed "FonT BASE character" comment
; > (also patched for latest zmac with default args)
; >
; > This file contains the equates and macros that Bally
; > programs require for assembly. This file has been
; > written to assemble with ZMAC 1.3 (a freely distribut-
; > able Z-80 assembler (with C source), that has a 25-year
; > history. ZMAC can be compiled under just about any O.S.
; > in existence, so try it out. This file will probably
; > require changes to be assembled under other assemblers.
; >
; > To assemble your Z-80 source code using ZMAC:
; >
; > zmac -d -o <outfile> -x <listfile> <filename>
; >
; > For example, assemble this Astrocade Z-80 ROM file:
; >
; > zmac -d -o BallyROM.bin -x BallyROM.lst BallyROM.asm
; >
; > Currently the Listing file is full of 'Undeclared'
; > errors. When all of the source is typed-in, these will
; > vanish. I'm leaving the others until all the source is
; > re-typed.
; >
;
; ***************************
; * Home Video Game EQUates *
; ***************************
;
; ASSEMBLY CONTROL
;
XPNDON EQU 1 ; ** SET TO 1 WHEN HARDWARE EXP
NWHDWR EQU 1 ; ** SET TO 1 WHEN NEW HARDWARE
;
; General goodies (HEX and Decimal values):
NORMEM EQU $4000 ; 8192 ; NORmal MEMory start
FIRSTC EQU $2000 ; 4096 ; FIRST address in Cartridge
SCREEN EQU $0000 ; 0 ; magic SCREEN start
BYTEPL EQU $28 ; 40 ; BYTEs Per Line
BITSPL EQU $A0 ; 160 ; BITS Per Line
;
; Stuff in SYSTEM DOPE VECTOR (valid for ALL system ROMs):
STIMER EQU $0200 ; Seconds and game TIMER, music
CTIMER EQU $0203 ; Custom TIMERs
FNTSYS EQU $0206 ; FoNT descriptor for SYStem font
FNTSML EQU $020D ; FoNT descriptor for SMaLl font
ALKEYS EQU $0214 ; ALl KEYS keypad mask
MENUST EQU $0218 ; head of onboard MENU STart
MXSCR EQU $021E ; address of 'MaX SCoRe' text string
NOPLAY EQU $0228 ; address of 'Number Of PLAYers' string
NOGAME EQU $0235 ; address of 'Number Of GAMEs' string
;
; BITS in PROCESSOR FLAG byte:
PSWCY EQU 0 ; Processor Status Word, CarrY bit
PSWPV EQU 2 ; Processor Status Word, Parity or oVerflow bit
PSWZRO EQU 6 ; Processor Status Word, ZeRO bit
PSWSGN EQU 7 ; Processor Status Word, SiGN bit
;
; BITS in GAME STATUS Byte:
GSBTIM EQU 0 ; Game Status Byte, if TIMe is up set end bit
GSBSCR EQU 1 ; Game Status Byte, if SCoRe reached set end bit
GSBEND EQU 7 ; Game Status Byte, END flag bit
;
; Standard VECTOR DISPLACEMENTS and bits:
VBMR EQU $00 ; +0 ; Vector Block, Magic Register
VBSTAT EQU $01 ; +1 ; Vector Block, STATus byte
VBTIMB EQU $02 ; +2 ; Vector Block, TIMe Base
VBDXL EQU $03 ; +3 ; Vector Block, Delta for X Low
VBDXH EQU $04 ; +4 ; Vector Block, Delta for X Hi
VBXL EQU $05 ; +5 ; Vector Block, X coord Low
VBXH EQU $06 ; +6 ; Vector Block, X coord Hi
VBXCHK EQU $07 ; +7 ; Vector Block, X CHecK flags
VBDYL EQU $08 ; +8 ; Vector Block, Delta for Y Low
VBDYH EQU $09 ; +9 ; Vector Block, Delta for Y Hi
VBYL EQU $0A ; +10 ; Vector Block, Y coord Low
VBYH EQU $0B ; +11 ; Vector Block, Y coord Hi
VBYCHK EQU $0C ; +12 ; Vector Block, Y CHecK flags
VBOAL EQU $0D ; +13 ; Vector Block, Old Address Low
VBOAH EQU $0E ; +14 ; Vector Block, Old Address Hi
;
; DISPLACEMENTS from start of COORDINATE AREA (X or Y):
VBDCL EQU $00 ; +0 ; Vector Block, Delta for Coord Low
VBDCH EQU $01 ; +1 ; Vector Block, Delta for Coord Hi
VBCL EQU $02 ; +2 ; Vector Block, Coord Low
VBCH EQU $03 ; +3 ; Vector Block, Coord Hi
VBCCHK EQU $04 ; +4 ; Vector Block, Coord CHecK flags
;
; BITS in STATUS byte:
VBBLNK EQU 6 ; Vector Block status, BLaNK bit
VBSACT EQU 7 ; Vector Block Status, ACTive bit
;
; BITS in (X or Y) VB CHECK FLAG bit mask:
VBCLMT EQU 0 ; Vector Block Check, LiMiT bit
VBCREV EQU 1 ; Vector Block Check, REVerse delta on limit attain
VBCLAT EQU 3 ; Vector Block Check, coordinate Limit ATtained
;
; FONT TABLE DISPLACEMENTS for CHARACTER DESCRIPTOR BLOCK:
FTBASE EQU $00 ; +0 ; FonT BASE character (normally $A0)
FTFSX EQU $01 ; +1 ; FonT Frame X Size width
FTFSY EQU $02 ; +2 ; FonT Frame Y Size height
FTBYTE EQU $03 ; +3 ; FonT X size for char in BYTEs
FTYSIZ EQU $04 ; +4 ; FonT Y SIZe height in rows
FTPTL EQU $05 ; +5 ; FonT Pattern Table address Low
FTPTH EQU $06 ; +6 ; FonT Pattern Table address Hi
;
; BITS for MAGIC REGISTER (write option) byte:
MRSHFT EQU $03 ; Magic Register, mask of SHiFT amount 0-3
MRROT EQU 2 ; Magic Register, write with ROTata bit
MRXPND EQU 3 ; Magic Register, write with eXPaND bit
MROR EQU 4 ; Magic Register, write with OR bit
MRXOR EQU 5 ; Magic Register, write with eXclusive-OR bit
MRFLOP EQU 6 ; Magic Register, write with FLOP bit
;
; BITS of CONTROL HANDLE Input port:
CHUP EQU 0 ; Control Handle, UP bit
CHDOWN EQU 1 ; Control Handle, DOWN bit
CHLEFT EQU 2 ; Control Handle, joystick LEFT bit
CHRIGH EQU 3 ; Control Handle, joystick RIGHT bit
CHTRIG EQU 4 ; Control Handle, TRIGger bit
;
; CONTEXT BLOCK Register DISPLACEMENTS:
CBIYL EQU $00 ; +0 ; Context Block, IY register Low
CBIYH EQU $01 ; +1 ; Context Block, IY register Hi
CBIXL EQU $02 ; +2 ; Context Block, IX register Low
CBIXH EQU $03 ; +3 ; Context Block, IX register Hi
CBE EQU $04 ; +4 ; Context Block, E register
CBD EQU $05 ; +5 ; Context Block, D register
CBC EQU $06 ; +6 ; Context Block, C register
CBB EQU $07 ; +7 ; Context Block, B register
CBFLAG EQU $08 ; +8 ; Context Block, FLAGs register
CBA EQU $09 ; +9 ; Context Block, A register
CBL EQU $0A ; +10 ; Context Block, L register
CBH EQU $0B ; +11 ; Context Block, H register
;
; SENTRY RETURN Codes EQUates:
SNUL EQU $00 ; Sentry return NULl, nothing happened
SCT0 EQU $01 ; Sentry, Counter-Timer 0 has counted down
SCT1 EQU $02 ; Sentry, Counter-Timer 1 has counted down
SCT2 EQU $03 ; Sentry, Counter-Timer 2 has counted down
SCT3 EQU $04 ; Sentry, Counter-Timer 3 has counted down
SCT4 EQU $05 ; Sentry, Counter-Timer 4 has counted down
SCT5 EQU $06 ; Sentry, Counter-Timer 5 has counted down
SCT6 EQU $07 ; Sentry, Counter-Timer 6 has counted down
SCT7 EQU $08 ; Sentry, Counter-Timer 7 has counted down
SF0 EQU $09 ; Sentry, Flag bit 0 has changed
SF1 EQU $0A ; Sentry, Flag bit 1 has changed
SF2 EQU $0B ; Sentry, Flag bit 2 has changed
SF3 EQU $0C ; Sentry, Flag bit 3 has changed
SF4 EQU $0D ; Sentry, Flag bit 4 has changed
SF5 EQU $0E ; Sentry, Flag bit 5 has changed
SF6 EQU $0F ; Sentry, Flag bit 6 has changed
SF7 EQU $10 ; Sentry, Flag bit 7 has changed
SSEC EQU $11 ; Sentry, SEConds timer has counted down
SKYU EQU $12 ; Sentry, KeY is now Up
SKYD EQU $13 ; Sentry, KeY is now Down
ST0 EQU $14 ; Sentry, Trigger 0 for player 1 has changed
SJ0 EQU $15 ; Sentry, Joystick 0 for player 1 has changed
ST1 EQU $16 ; Sentry, Trigger 1 for player 2 has changed
SJ1 EQU $17 ; Sentry, Joystick 1 for player 2 has changed
ST2 EQU $18 ; Sentry, Trigger 2 for player 3 has changed
SJ2 EQU $19 ; Sentry, Joystick 2 for player 3 has changed
ST3 EQU $1A ; Sentry, Trigger 3 for player 4 has changed
SJ3 EQU $1B ; Sentry, Joystick 3 for player 4 has changed
SP0 EQU $1C ; Sentry, POTentiometer 0 has changed
SP1 EQU $1D ; Sentry, POTentiometer 1 has changed
SP2 EQU $1E ; Sentry, POTentiometer 2 has changed
SP3 EQU $1F ; Sentry, POTentiometer 3 has changed
;
;
; ********************************
; * Home Video Game PORT EQUates *
; ********************************
;
; OUTPUT Ports for VIRTUAL COLOR:
COL0R EQU $00 ; &(0)= ; write COLor 0 Right
COL1R EQU $01 ; &(1)= ; write COLor 1 Right
COL2R EQU $02 ; &(2)= ; write COLor 2 Right
COL3R EQU $03 ; &(3)= ; write COLor 3 Right
COL0L EQU $04 ; &(4)= ; write COLor 0 Left
COL1L EQU $05 ; &(5)= ; write COLor 1 Left
COL2L EQU $06 ; &(6)= ; write COLor 2 Left
COL3L EQU $07 ; &(7)= ; write COLor 3 Left
HORCB EQU $09 ; &(9)= ; write HORizontal Color Boundary
VERBL EQU $0A ;&(10)= ; write VERtical Blanking Line
COLBX EQU $0B ;&(11)= ; write COLor BloCK multi-port
;
; OUTPUT Ports for MUSIC and SOUNDS:
TONMO EQU $10 ;&(16)= ; write TONe Master Oscillator
TONEA EQU $11 ;&(17)= ; write TONe A oscillator
TONEB EQU $12 ;&(18)= ; write TONe B oscillator
TONEC EQU $13 ;&(19)= ; write TONe C oscillator
VIBRA EQU $14 ;&(20)= ; write VIBRAto frequency & range
VOLC EQU $15 ;&(21)= ; write VOLume of tone C
VOLAB EQU $16 ;&(22)= ; write VOLumes of tones A & B
VOLN EQU $17 ;&(23)= ; write VOLume of Noise
SNDBX EQU $18 ;&(24)= ; write SouND BloCK multi-port
;
; INTERRUPT and CONTROL OUTPUT Ports:
CONCM EQU $08 ; &(8)= ; write 0 for CONsumer, 1 for CoMmercial mode
MAGIC EQU $0C ;&(12)= ; write MAGIC register
INFBK EQU $0D ;&(13)= ; write INterrupt FeedBacK
INMOD EQU $0E ;&(14)= ; write INterrupt MODe
INLIN EQU $0F ;&(15)= ; write INterrupt LINe
XPAND EQU $19 ;&(25)= ; eXPANDer pixel definition port
;
; INTERRUPT and INTERCEPT INPUT Ports:
INTST EQU $08 ; =&(8) ; read INTercept STatus
VERAF EQU $0E ;=&(14) ; read VERtical Address Feedback
HORAF EQU $0F ;=&(15) ; read HORizontal Address Feedback
;
; HAND CONTROL INPUT Ports:
SW0 EQU $10 ;=&(16) ; read SWitch bank 0 for player 1 hand control
SW1 EQU $11 ;=&(17) ; read SWitch bank 1 for player 2 hand control
SW2 EQU $12 ;=&(18) ; read SWitch bank 2 for player 3 hand control
SW3 EQU $13 ;=&(19) ; read SWitch bank 3 for player 4 hand control
POT0 EQU $1C ;=&(28) ; read POTentiometer 0 for player 1 knob
POT1 EQU $1D ;=&(29) ; read POTentiometer 1 for player 2 knob
POT2 EQU $1E ;=&(30) ; read POTentiometer 2 for player 3 knob
POT3 EQU $1F ;=&(31) ; read POTentiometer 3 for player 4 knob
;
; KEYBOARD INPUT Ports:
KEY0 EQU $14 ;=&(20) ; KEYboard column 0 (right side)
KEY1 EQU $15 ;=&(21) ; KEYboard column 1 (center right)
KEY2 EQU $16 ;=&(22) ; KEYboard column 2 (center left)
KEY3 EQU $17 ;=&(23) ; KEYboard column 3 (left side)
;
;
; ***************************************
; * Home Video Game SYSTEM CALL Indexes *
; ***************************************
;
; USER PROGRAM Interface:
INTPC EQU $00 ; # 0 ; INTerPret with Context create
XINTC EQU $02 ; # 2 ; eXit INTerpreter with Context
RCALL EQU $04 ; # 4 ; Real CALL asm language subroutine
MCALL EQU $06 ; # 6 ; Macro CALL interpreter subroutine
MRET EQU $08 ; # 8 ; Macro RETurn from interpreter subroutine
MJUMP EQU $0A ; # 10 ; Macro JUMP to interpreter subroutine
SUCK EQU $0C ; # 12 ; SUCK inline args into context block
;
; SCHEDULER Routines:
ACTINT EQU $0E ; # 14 ; ACTivate sub timer INTerrupts
DECCTS EQU $10 ; # 16 ; DECrement CT'S under mask
;
; MUSIC and SOUNDS:
BMUSIC EQU $12 ; # 18 ; Begin playing MUSIC
EMUSIC EQU $14 ; # 20 ; End playing MUSIC
;
; SCREEN HANDLER Routines:
SETOUT EQU $16 ; # 22 ; SET some OUTput ports
COLSET EQU $18 ; # 24 ; COLors SET
FILL EQU $1A ; # 26 ; FILL memory with data
RECTAN EQU $1C ; # 28 ; paint a RECTANgle
VWRITR EQU $1E ; # 30 ; Vector WRITe Relative
WRITR EQU $20 ; # 32 ; WRITe Relative
WRITP EQU $22 ; # 34 ; WRITe with Pattern size lookup
WRIT EQU $24 ; # 36 ; WRITe with sizes provided
WRITA EQU $26 ; # 38 ; WRITe Absolute
VBLANK EQU $28 ; # 40 ; Vector BLANK area
BLANK EQU $2A ; # 42 ; BLANK area
SAVE EQU $2C ; # 44 ; SAVE area
RESTOR EQU $2E ; # 46 ; RESTORe area
SCROLL EQU $30 ; # 48 ; SCROLL area of screen
;
CHRDIS EQU $32 ; # 50 ; CHaRacter DISplay
STRDIS EQU $34 ; # 52 ; STRing DISplay
DISNUM EQU $36 ; # 54 ; DISplay NUMber
;
RELABS EQU $38 ; # 56 ; RELative to ABSolute conversion
RELAB1 EQU $3A ; # 58 ; RELative to non-magic ABSolute
VECTC EQU $3C ; # 60 ; VECTor move single Coordinate
VECT EQU $3E ; # 62 ; VECTor move coordinate pair
;
; HUMAN INTERFACE Routines:
KCTASC EQU $40 ; # 64 ; Key Code in B To ASCii
SENTRY EQU $42 ; # 66 ; SENse TRansition Y
DOIT EQU $44 ; # 68 ; DOIT table, branch to translation handler
DOITB EQU $46 ; # 70 ; DOIT table, use B instead of A
PIZBRK EQU $48 ; # 72 ; take a PIZza BReaK
MENU EQU $4A ; # 74 ; display a MENU
GETPAR EQU $4C ; # 76 ; GET game PARameter from user
GETNUM EQU $4E ; # 78 ; GET NUMber from user
PAWS EQU $50 ; # 80 ; PAUSE
DISTIM EQU $52 ; # 82 ; DISplay TIMe
INCSCR EQU $54 ; # 84 ; INCrement SCoRe
;
; MATH Routines:
INDEXN EQU $56 ; # 86 ; INDEX Nibble by C
STOREN EQU $58 ; # 88 ; STORE Nibble in A by C
INDEXW EQU $5A ; # 90 ; INDEX Word by A
INDEXB EQU $5C ; # 92 ; INDEX Byte by A
MOVE EQU $5E ; # 94 ; MOVE block transfer
SHIFTU EQU $60 ; # 96 ; SHIFT Up digit in A
BCDADD EQU $62 ; # 98 ; BCD ADDition
BCDSUB EQU $64 ;# 100 ; BCD SUBtraction
BCDMUL EQU $66 ;# 102 ; BCD MULtiplication
BCDDIV EQU $68 ;# 104 ; BCD DIVision
BCDCHS EQU $6A ;# 106 ; BCD CHange Sign
BCDNEG EQU $6C ;# 108 ; BCD NEGate to decimal
DADD EQU $6E ;# 110 ; Decimal ADDition
DSMG EQU $70 ;# 112 ; Decimal convert to Sign MaGnitude
DABS EQU $72 ;# 114 ; Decimal ABSolute value
NEGT EQU $74 ;# 116 ; decimal NEGaTe
RANGED EQU $76 ;# 118 ; RANGED random number
QUIT EQU $78 ;# 120 ; QUIT cassette execution
SETB EQU $7A ;# 122 ; SET Byte
SETW EQU $7C ;# 124 ; SET Word
MSKTD EQU $7E ;# 127 ; MaSK joystick in B To Deltas
;
;
; **********
; * MACROS *
; **********
; Assembler directives in lower case to distinguish from OPCODEs.
;
; MACROs to define PATTERNs:
DEF2 macro AA,AB
DB AA
DB AB
endm
DEF3 macro BA,BB,BCC
DB BA
DB BB
DB BCC ; 'BC' reserved, so used 'BCC'
endm
DEF4 macro CA,CB,CC,CD
DB CA
DB CB
DB CC
DB CD
endm
DEF5 macro DA,DBB,DC,DD,DEE
DB DA
DB DBB
DB DC
DB DD
DB DEE
endm
DEF6 macro EA,EB,EC,ED,EE,EF
DB EA
DB EB
DB EC
DB ED
DB EE
DB EF
endm
DEF8 macro GA,GB,GC,GD,GEE,GF,GG,GH
DB GA
DB GB
DB GC
DB GD
DB GEE ; 'GE' reserved, so used 'GEE'
DB GF
DB GG
DB GH
endm
;
; MACRO to compute CONSTANT SCREEN Addresses:
XYRELL macro p1,p2,p3 ; RELative LOAD
LD p1,[(p3 SHL 8) + p2]
endm
;
; MACROs to generate SYSTEM CALLs:
SYSTEM macro NUMBA
RST $38
DB NUMBA
if NUMBA = INTPC
INTPCC DEFL 1
endif
endm
; MACRO to generate SYSTEM CALL with SUCK option ON:
SYSSUK macro UMBA
RST $38
DB UMBA + 1
if UMBA = INTPC
INTPCC DEFL 1
endif
endm
;
; MACROs to generate MACRO INTERPRETER CALLs:
; INTERPRET without INLINE SUCK:
DONT macro CID
DB CID
endm
; INTERPRET with INLINE SUCK option ON:
DO macro CID
DB CID + 1
endm
;
; FILL screen with constant data (was 'FILL?'):
FILLq macro START,NBYTES,DATA
DB FILL + 1
DW START
DW NBYTES
DB DATA
endm
; DISPLAY a STRING: (only inside interpreter?)
TEXTD macro AA,BB,CC,DD
DB STRDIS + 1
DB BB
DB CC
DB DD
DW AA
endm
;
; EXIT interpreter with context restore:
EXIT macro
DB XINTC
INTPCC DEFL 0
endm
;
ENDx EQU $C0 ; END of DOIT Table
;
; MACRO CALLs from DOIT Table (only):
MCALL macro AA, BB, EE
DB AA + $80
DW BB
if EE = ENDx
DB EE
endif
endm
; REAL CALL from DOIT Table:
RCALL macro AA,BB,EE
DB AA + $40
DW BB
if EE = ENDx
DB EE
endif
endm
; REAL JUMP from DOIT Table:
JMPd macro AA,BB,EE
DB AA
DW BB
if EE = ENDx
DB EE
endif
endm
;
;**************
; MUSIC MACROS:
; $00 to $7F = NOTE DURation, FREQuency(s):
NOTE1 macro DUR,N1
DB (DUR) AND ($7F)
DB N1
endm
NOTE2 macro DUR,N1,N2
DB (DUR) AND ($7F)
DB N1
DB N2
endm
NOTE3 macro DUR,N1,N2,N3
DB (DUR) AND ($7F)
DB N1
DB N2
DB N3
endm
NOTE4 macro DUR,N1,N2,N3,N4
DB (DUR) AND ($7F)
DB N1
DB N2
DB N3
DB N4
endm
NOTE5 macro DUR,N1,N2,N3,N4,N5
DB (DUR) AND ($7F)
DB N1
DB N2
DB N3
DB N4
DB N5
endm
; $80 = Set MASTER Osc, Offset:
MASTER macro OFFSET
DB $80
DB OFFSET
endm
; $80 to $88 = Stuff OUTPUT Port# (0 to 7 only!), Data
; or OUTPUT SNDBX, Data10, D11,..., Data17:
OUTPUT macro PORT,D0,D1,D2,D3,D4,D5,D6,D7
if PORT != $18
DB $80 + ((PORT) AND ($7F))
DB D0 ; <-- D0 is NOT $D0
else ; on PORT = $18
DB $88
DEF8 D7,D6,D5,D4,D3,D2,D1,D0
endif
endm
; $90 = Set VOICE MASK byte:
; The format of the Voice MASK is:
; * I * A * I * B * I * C * V * N *
; bit 7 6 5 4 3 2 1 0
; read right-to-left, where I = INC PC and
; A, B, or C = load TONE A,B,C with data at PC
; V = load Vibrato with data at PC and INC PC
; N = load Noise with data at PC and INC PC
VOICEM macro MASK ; 'VOICES' TO 'VOICEM'
DB $90
DB MASK
endm
; $A0 to $AF = PUSH Number 1 to 16 onto music stack:
PUSHN macro NUMB
DB $A0 + ((NUMB-1) AND $0F)
endm
; $BO = Set VOLUMEs:
VOLUME macro P1,P2
DB $B0
DB P1
DB P2
endm
; $C0 = Dec Stack top and JNZ:
DSJNZ macro ADD_IT
DB $C0
DW ADD_IT
endm
; note: Music Processor also uses standard codes as $C3 for
; music JumP, $C9 for music RETurn, and $CD for music CALL.
;
; $D0 = Call RELative self+1 plus 0 to 15:
CREL macro BY
DB $D0 + (BY AND $0F)
endm
; $E0 = Flip LEGatto to STAcato:
LEGSTA macro
DB $E0
endm
REST macro TIME
DB $E1
DB TIME
endm
QUIET macro
DB $F0
endm
;
; *****************
; * MUSIC EQUATES *
; *****************
; NOTE Values:
G0 EQU $FD ; 253
GS0 EQU $EE ; 238
A0 EQU $E1 ; 225
AS0 EQU $D4 ; 212
B0 EQU $C8 ; 200
C1 EQU $BD ; 189
CS1 EQU $B2 ; 178
D1 EQU $A8 ; 168
DS1 EQU $9F ; 159
E1 EQU $96 ; 150
F1 EQU $8D ; 141
FS1 EQU $85 ; 133
G1 EQU $7E ; 126
GS1 EQU $77 ; 119
A1 EQU $70 ; 112
AS1 EQU $6A ; 106
B1 EQU $64 ; 100
C2 EQU $5E ; 94
CS2 EQU $59 ; 89
D2 EQU $54 ; 84
DS2 EQU $4F ; 79
E2 EQU $4A ; 74
F2 EQU $46 ; 70
FS2 EQU $42 ; 66
G2 EQU $3E ; 62
GS2 EQU $3B ; 59
A2 EQU $37 ; 55
AS2 EQU $34 ; 52
B2 EQU $31 ; 49
C3 EQU $2E ; 46
CS3 EQU $2C ; 44
D3 EQU $29 ; 41
DS3 EQU $27 ; 39
E3 EQU $25 ; 37
F3 EQU $22 ; 34
FS3 EQU $20 ; 32
G3 EQU $1F ; 31
GS3 EQU $1D ; 29
A3 EQU $1B ; 27
AS3 EQU $1A ; 26
B3 EQU $18 ; 24
C4 EQU $17 ; 23
CS4 EQU $15 ; 21
D4 EQU $14 ; 20
DS4 EQU $13 ; 19
E4 EQU $12 ; 18
F4 EQU $11 ; 17
FS4 EQU $10 ; 16
G4 EQU $0F ; 15
GS4 EQU $0E ; 14
A4 EQU $0D ; 13
C5 EQU $0B ; 11
CS5 EQU $0A ; 10
DS5 EQU $09 ; 9
F5 EQU $08 ; 8
G5 EQU $07 ; 7
A5 EQU $06 ; 6
C6 EQU $05 ; 5
DS6 EQU $04 ; 4
G6 EQU $03 ; 3
C7 EQU $02 ; 2
G7 EQU $01 ; 1
G8 EQU $00 ; 0
;
; MASTER OSCILATOR Offsets:
OB0 EQU $FE ; 254
OC0 EQU $F1 ; 241
OD1 EQU $D6 ; 214
OE1 EQU $BF ; 191
OF1 EQU $B4 ; 180
OG1 EQU $A0 ; 160
OA1 EQU $8F ; 143
OA2 EQU $47 ; 71
OA3 EQU $23 ; 35
OA4 EQU $11 ; 17
OA5 EQU $08 ; 8
;
;
; ***************************
; * SYSTEM RAM MEMORY Cells *
; ***************************
WASTE EQU $0FFF
WASTER EQU WASTE
;
SYSRAM EQU $4FCE ; Resides at the highest possible address
BEGRAM EQU SYSRAM ; typically used for initial Stack Pointer
; Used by MUSIC PROCESSOR:
MUZPC EQU $4FCE ; MUSic Program Counter
MUZSP EQU $4FD0 ; MUSic Stack Pointer
PVOLAB EQU $4FD2 ; Preset VOLume for tones A and B
PVOLMC EQU $4FD3 ; Preset VOLuMe for tone C and Noise Mode
VOICES EQU $4FD4 ; music VOICES mask
; COUNTER TIMERS (used by DECCTS,ACTINT,CTIMER):
CT0 EQU $4FD5 ; Counter Timer 0
CT1 EQU $4FD6 ; Counter Timer 1
CT2 EQU $4FD7 ; Counter Timer 2
CT3 EQU $4FD8 ; Counter Timer 3
CT4 EQU $4FD9 ; Counter Timer 4
CT5 EQU $4FDA ; Counter Timer 5
CT6 EQU $4FDB ; Counter Timer 6
CT7 EQU $4FDC ; Counter Timer 7
;Used by SENTRY to track controls:
CNT EQU $4FDD ; Counter update & Number Tracking
SEMI4S EQU $4FDE ; SEMAPHORE flag bitS
OPOT0 EQU $4FDF ; Old POT 0 tracking byte
OPOT1 EQU $4FE0 ; Old POT 1 tracking byte
OPOT2 EQU $4FE1 ; Old POT 2 tracking byte
OPOT3 EQU $4FE2 ; Old POT 3 tracking byte
KEYSEX EQU $4FE3 ; KEYS-EX tracking byte
OSW0 EQU $4FE4 ; Old SWitch 0 tracking byte
OSW1 EQU $4FE5 ; Old SWitch 1 tracking byte
OSW2 EQU $4FE6 ; Old SWitch 2 tracking byte
OSW3 EQU $4FE7 ; Old SWitch 3 tracking byte
COLLST EQU $4FE8 ; COLset LaST address for P.B. A
; Used by STIMER:
DURAT EQU $4FEA ; note DURATion
TMR60 EQU $4FEB ; TiMeR for SIXTY'ths of sec
TIMOUT EQU $4FEC ; TIMer for blackOUT
GTSECS EQU $4FED ; Game Time SECondS
GTMINS EQU $4FEE ; Game Time MINuteS
; Used by MENU:
RANSHT EQU $4FEF ; RANdom number SHifT register
NUMPLY EQU $4FF3 ; NUMber of PLaYers
ENDSCR EQU $4FF4 ; END SCoRe to 'play to'
MRLOCK EQU $4FF7 ; Magic Register LOCK out flag
GAMSTB EQU $4FF8 ; GAMe STatus Byte
PRIOR EQU $4FF9 ; PRIOR music protect flag
SENFLG EQU $4FFA ; SENtry control seizure FLaG
; User UPI Routines, even numbers from $80 to $FE ( + 1 for SUCK):
UMARGT EQU $4FFB ; User Mask ARGument Table + (routine / 2)
USERTB EQU $4FFD ; USER Table Base + routine = JumP address
;
URINAL EQU $4FFF ; WASTER flushes here!
;
;

View File

@ -3,36 +3,41 @@
// from TSS
declare var MasterChannel, AudioLooper, PsgDeviceChannel;
export var MasterAudio = function() {
this.master = new MasterChannel();
this.looper = new AudioLooper(512);
this.start = function() {
export class MasterAudio {
master = new MasterChannel();
looper = new AudioLooper(512);
start() {
this.looper.setChannel(this.master);
this.looper.activate();
}
this.stop = function() {
stop() {
this.looper.setChannel(null);
}
}
export var AY38910_Audio = function(master) {
this.psg = new PsgDeviceChannel();
this.psg.setMode(PsgDeviceChannel.MODE_SIGNED);
this.psg.setDevice(PsgDeviceChannel.DEVICE_AY_3_8910);
master.master.addChannel(this.psg);
var curreg = 0;
export class AY38910_Audio {
master : MasterAudio;
psg = new PsgDeviceChannel();
curreg = 0;
constructor(master : MasterAudio) {
this.master = master;
this.psg.setMode(PsgDeviceChannel.MODE_SIGNED);
this.psg.setDevice(PsgDeviceChannel.DEVICE_AY_3_8910);
master.master.addChannel(this.psg);
}
this.reset = function() {
reset() {
for (var i=15; i>=0; i--) {
this.selectRegister(i);
this.setData(0);
}
}
this.selectRegister = function(val) {
curreg = val & 0xf;
selectRegister(val : number) {
this.curreg = val & 0xf;
}
this.setData = function(val) {
this.psg.writeRegisterAY(curreg, val & 0xff);
setData(val : number) {
this.psg.writeRegisterAY(this.curreg, val & 0xff);
}
}

View File

@ -168,6 +168,7 @@ export abstract class BaseDebugPlatform extends BasePlatform {
}
}
// TODO: what's the diff? why z80 not use? unify these things
export abstract class BaseFrameBasedPlatform extends BaseDebugPlatform {
debugPCDelta = -1;
@ -245,6 +246,12 @@ export abstract class BaseFrameBasedPlatform extends BaseDebugPlatform {
return false;
});
}
/*
runToVsync() {
this.nextFrame(false);
this.runEval(() => { return true; });
}
*/
}
////// 6502

View File

@ -106,7 +106,7 @@ memory.write(regPairs[11], regPairs[12] & 0xff);;
l = (tstates += ( 3), memory.read(inttemp));
inttemp = (inttemp+1) & 0xffff;
h = (tstates += ( 3), memory.read(inttemp));
console.log(hex(interruptDataBus), hex(inttemp), hex(l), hex(h));
//console.log(hex(interruptDataBus), hex(inttemp), hex(l), hex(h));
regPairs[12] = (h<<8) | l;
tstates += 7;
break;

369
src/platform/astrocade.ts Normal file
View File

@ -0,0 +1,369 @@
"use strict";
import { Platform, BaseZ80Platform } from "../baseplatform";
import { PLATFORMS, RAM, newAddressDecoder, padBytes, noise, setKeyboardFromMap, AnimationTimer, RasterVideo, Keys, makeKeycodeMap } from "../emu";
import { hex, lzgmini, stringToByteArray } from "../util";
import { MasterAudio, AY38910_Audio } from "../audio";
const ASTROCADE_PRESETS = [
{id:'01-helloworlds.asm', name:'Hello World'},
{id:'02-telephone.asm', name:'Telephone'},
{id:'03-horcbpal.asm', name:'Paddle Demo'},
];
// TODO: fix keys, more controllers, paddles, vibrato/noise, border color
const ASTROCADE_KEYCODE_MAP = makeKeycodeMap([
// player 1
[Keys.VK_UP, 0x10, 0x1],
[Keys.VK_DOWN, 0x10, 0x2],
[Keys.VK_LEFT, 0x10, 0x4],
[Keys.VK_RIGHT, 0x10, 0x8],
[Keys.VK_SPACE, 0x10, 0x10],
// keypad $14
[Keys.VK_P, 0x14, 0x1],
[Keys.VK_SLASH, 0x14, 0x2],
[Keys.VK_X, 0x14, 0x4],
[Keys.VK_MINUS, 0x14, 0x8],
[Keys.VK_COMMA, 0x14, 0x10],
[Keys.VK_EQUALS,0x14, 0x20],
// keypad $15
[Keys.VK_Z, 0x15, 0x1],
[Keys.VK_H, 0x15, 0x2],
[Keys.VK_9, 0x15, 0x4],
[Keys.VK_6, 0x15, 0x8],
[Keys.VK_3, 0x15, 0x10],
[Keys.VK_PERIOD,0x15, 0x20],
// keypad $16
[Keys.VK_A, 0x16, 0x1],
[Keys.VK_S, 0x16, 0x2],
[Keys.VK_8, 0x16, 0x4],
[Keys.VK_5, 0x16, 0x8],
[Keys.VK_2, 0x16, 0x10],
[Keys.VK_0, 0x16, 0x20],
// keypad $17
[Keys.VK_C, 0x17, 0x1],
[Keys.VK_R, 0x17, 0x2],
[Keys.VK_7, 0x17, 0x4],
[Keys.VK_4, 0x17, 0x8],
[Keys.VK_1, 0x17, 0x10],
[Keys.VK_E, 0x17, 0x20],
]);
const _BallyAstrocadePlatform = function(mainElement) {
var cpu, ram, membus, iobus, rom, bios;
var probe;
var video, timer, pixels;
var audio, psg;
var inputs = new Uint8Array(0x20);
//var watchdog_counter;
const swidth = 160;
const sheight = 102;
const cpuFrequency = 1789000;
const cpuCyclesPerLine = cpuFrequency/(60*sheight);
const INITIAL_WATCHDOG = 256;
const PIXEL_ON = 0xffeeeeee;
const PIXEL_OFF = 0xff000000;
var magicop = 0;
var xpand = 0;
var xplower = false;
var shift2 = 0;
var horcb = 0;
var inmod = 0;
var inlin = 0;
var infbk = 0;
var verbl = sheight;
var palette = new Uint32Array(8);
// default palette
for (var i=0; i<8; i++)
palette[i] = ASTROCADE_PALETTE[i];
function ramwrite(a:number, v:number) {
ram.mem[a] = v;
var ofs = a*4+3; // 4 pixels per byte
for (var i=0; i<4; i++) {
var lr = ((a % 0x28) >= (horcb & 0x3f)) ? 0 : 4;
pixels[ofs--] = palette[lr + (v & 3)];
v >>= 2;
}
}
function magicwrite(a:number, v:number) {
// expand
if (magicop & 0x8) {
var v2 = 0;
if (!xplower)
v >>= 4;
for (var i=0; i<4; i++) {
var pix = (v&1) ? ((xpand>>2)&3) : (xpand&3);
v2 |= pix << (i*2);
v >>= 1;
}
v = v2;
xplower = !xplower;
}
// shift
var sh = (magicop & 3) << 1;
var v2 = (v >> sh) | shift2;
shift2 = (v << (8-sh)) & 0xff;
v = v2;
// flop
if (magicop & 0x40) {
var v2 = 0;
for (var i=0; i<4; i++) {
v2 |= (v & 3) << (6-i*2);
v >>= 2;
}
v = v2;
}
// or/xor
if (magicop & 0x30) {
var oldv = ram.mem[a];
if (magicop & 0x10)
v |= oldv;
if (magicop & 0x20)
v ^= oldv; // TODO: what if both?
// collision detect
var icpt = 0;
for (var i=0; i<8; i+=2) {
icpt <<= 1;
// pixel changed from off to on?
if ( !((oldv>>i)&3) && ((v>>i)&3) )
icpt |= 1;
}
// upper 4 bits persist, lower are just since last write
inputs[8] = (inputs[8] & 0xf0) | icpt | (icpt<<4);
}
// commit write to ram/screen
ramwrite(a, v);
}
function setpalette(a:number, v:number) {
palette[a&7] = ASTROCADE_PALETTE[v&0xff];
}
function setbordercolor() {
var col = horcb >> 6;
// TODO
}
class BallyAstrocadePlatform extends BaseZ80Platform implements Platform {
getPresets() {
return ASTROCADE_PRESETS;
}
start = function() {
ram = new RAM(0x2000);
bios = new lzgmini().decode(stringToByteArray(atob(window['ASTROCADE_LZGROM'])));
//displayPCs = new Uint16Array(new ArrayBuffer(0x2000*2));
membus = {
read: newAddressDecoder([
[0x0000, 0x1fff, 0x1fff, function(a) { return bios ? bios[a] : 0; }],
[0x2000, 0x3fff, 0x1fff, function(a) { return rom ? rom[a] : 0; }],
[0x4000, 0x4fff, 0xfff, function(a) { return ram.mem[a]; }],
]),
write: newAddressDecoder([
[0x4000, 0x4fff, 0xfff, ramwrite],
[0x0000, 0x3fff, 0x3fff, magicwrite],
]),
isContended: function() { return false; },
};
iobus = {
read: function(addr) {
addr &= 0x1f;
var rtn = inputs[addr];
if (addr == 8)
inputs[addr] = 0;
return rtn;
},
write: function(addr, val) {
addr &= 0x1f;
val &= 0xff;
switch (addr) {
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
setpalette(addr,val);
break;
case 9: // HORCB (horizontal boundary byte)
horcb = val;
setbordercolor();
break;
case 0xa: // VERBL (vertical blank)
verbl = val >> 1;
break;
case 0xb: // OTIR (set palette)
setpalette(cpu.getBC()>>8, membus.read(cpu.getHL()));
break;
case 0xc: // magic register
magicop = val;
shift2 = 0;
break;
case 0xd: // INFBK (interrupt feedback)
infbk = val;
break;
case 0xe: // INMOD (interrupt enable)
inmod = val;
break;
case 0xf: // INLIN (interrupt line)
inlin = val >> 1;
break;
case 0x10:
case 0x11:
case 0x12:
case 0x13:
case 0x14:
case 0x15:
case 0x16:
case 0x17:
psg.setACRegister(addr, val);
break;
case 0x18:
psg.setACRegister(cpu.getBC()>>8, membus.read(cpu.getHL()));
break;
case 0x19: // XPAND
xpand = val;
xplower = false;
break;
default:
console.log('IO write', hex(addr,4), hex(val,2));
break;
}
}
};
cpu = this.newCPU(membus, iobus);
audio = new MasterAudio();
psg = new AstrocadeAudio(audio);
video = new RasterVideo(mainElement,swidth,sheight,{});
video.create();
var idata = video.getFrameData();
setKeyboardFromMap(video, inputs, ASTROCADE_KEYCODE_MAP);
pixels = video.getFrameData();
timer = new AnimationTimer(60, this.nextFrame.bind(this));
}
readAddress(addr) {
return membus.read(addr);
}
advance(novideo : boolean) {
for (var sl=0; sl<sheight; sl++) {
this.runCPU(cpu, cpuCyclesPerLine);
if (sl == inlin && (inmod & 0x8)) {
cpu.requestInterrupt(infbk);
}
}
if (!novideo) {
video.updateFrame(0, 0, 0, 0, swidth, verbl+2);
}
/*
if (watchdog_counter-- <= 0) {
console.log("WATCHDOG FIRED"); // TODO: alert on video
this.reset();
}
*/
}
loadROM(title, data) {
rom = padBytes(data, 0x2000);
this.reset();
}
loadState(state) {
cpu.loadState(state.c);
ram.mem.set(state.b);
palette.set(state.palette);
this.loadControlsState(state);
}
saveState() {
return {
c:this.getCPUState(),
b:ram.mem.slice(0),
in:inputs.slice(0),
palette:palette.slice(0),
};
}
loadControlsState(state) {
inputs.set(state.in);
}
saveControlsState() {
return {
in:inputs.slice(0)
};
}
getCPUState() {
return cpu.saveState();
}
isRunning() {
return timer && timer.isRunning();
}
pause() {
timer.stop();
audio.stop();
}
resume() {
timer.start();
audio.start();
}
reset() {
cpu.reset();
cpu.setTstates(0);
//watchdog_counter = INITIAL_WATCHDOG;
}
}
return new BallyAstrocadePlatform();
}
/////
class AstrocadeAudio extends AY38910_Audio {
setACRegister(addr : number, val : number) {
addr &= 0x7;
val &= 0xff;
//console.log(addr,val);
switch (addr) {
case 0:
this.psg.setClock(1789000 * 16 / (val + 1));
this.psg.writeRegisterAY(7, 0x7 ^ 0xff); // disable noise
break;
case 1:
case 2:
case 3:
var i = (addr-1)*2;
var j = val*2+1;
this.psg.writeRegisterAY(i, j&0xff); // freq lo
this.psg.writeRegisterAY(i+1, (j>>8)&0xff); // freq hi
console.log(i,j);
break;
case 5:
this.psg.writeRegisterAY(10, val & 0xf); // tone c vol
break;
case 6:
this.psg.writeRegisterAY(8, val & 0xf); // tone a vol
this.psg.writeRegisterAY(9, (val>>4) & 0xf); // tone b vol
break;
}
}
}
/////
PLATFORMS['astrocade'] = _BallyAstrocadePlatform;
//http://glankonian.com/~lance/astrocade_palette.html
var ASTROCADE_PALETTE = [0x000000,0x242424,0x484848,0x6D6D6D,0x919191,0xB6B6B6,0xDADADA,0xFFFFFF,0x2500BB,0x4900E0,0x6E11FF,0x9235FF,0xB75AFF,0xDB7EFF,0xFFA3FF,0xFFC7FF,0x4900B0,0x6D00D5,0x9201F9,0xB625FF,0xDA4AFF,0xFF6EFF,0xFF92FF,0xFFB7FF,0x6A009F,0x8E00C3,0xB300E7,0xD718FF,0xFB3CFF,0xFF61FF,0xFF85FF,0xFFA9FF,0x870087,0xAB00AB,0xD000D0,0xF40EF4,0xFF32FF,0xFF56FF,0xFF7BFF,0xFF9FFF,0x9F006A,0xC3008E,0xE700B3,0xFF07D7,0xFF2CFB,0xFF50FF,0xFF74FF,0xFF99FF,0xB00049,0xD5006D,0xF90092,0xFF05B6,0xFF29DA,0xFF4DFF,0xFF72FF,0xFF96FF,0xBB0025,0xE00049,0xFF006E,0xFF0692,0xFF2AB7,0xFF4FDB,0xFF73FF,0xFF98FF,0xBF0000,0xE30024,0xFF0048,0xFF0B6D,0xFF3091,0xFF54B6,0xFF79DA,0xFF9DFF,0xBB0000,0xE00000,0xFF0023,0xFF1447,0xFF396C,0xFF5D90,0xFF82B5,0xFFA6D9,0xB00000,0xD50000,0xF90000,0xFF2124,0xFF4548,0xFF6A6C,0xFF8E91,0xFFB3B5,0x9F0000,0xC30000,0xE70C00,0xFF3003,0xFF5527,0xFF794B,0xFF9E70,0xFFC294,0x870000,0xAB0000,0xD01E00,0xF44200,0xFF670A,0xFF8B2E,0xFFAF53,0xFFD477,0x6A0000,0x8E0D00,0xB33100,0xD75600,0xFB7A00,0xFF9E17,0xFFC33B,0xFFE75F,0x490000,0x6D2100,0x924500,0xB66A00,0xDA8E00,0xFFB305,0xFFD729,0xFFFC4E,0x251100,0x493500,0x6E5A00,0x927E00,0xB7A300,0xDBC700,0xFFEB1E,0xFFFF43,0x002500,0x244900,0x486D00,0x6D9200,0x91B600,0xB6DB00,0xDAFF1B,0xFFFF3F,0x003700,0x005B00,0x238000,0x47A400,0x6CC900,0x90ED00,0xB5FF1E,0xD9FF43,0x004700,0x006C00,0x009000,0x24B400,0x48D900,0x6CFD05,0x91FF29,0xB5FF4E,0x005500,0x007900,0x009D00,0x03C200,0x27E600,0x4BFF17,0x70FF3B,0x94FF5F,0x005F00,0x008300,0x00A800,0x00CC00,0x0AF00A,0x2EFF2E,0x53FF53,0x77FF77,0x006500,0x008A00,0x00AE00,0x00D203,0x00F727,0x17FF4B,0x3BFF70,0x5FFF94,0x006800,0x008C00,0x00B100,0x00D524,0x00F948,0x05FF6C,0x29FF91,0x4EFFB5,0x006600,0x008B00,0x00AF23,0x00D447,0x00F86C,0x00FF90,0x1EFFB5,0x43FFD9,0x006100,0x008524,0x00AA48,0x00CE6D,0x00F391,0x00FFB6,0x1BFFDA,0x3FFFFE,0x005825,0x007C49,0x00A16E,0x00C592,0x00EAB7,0x00FFDB,0x1EFFFF,0x43FFFF,0x004B49,0x00706D,0x009492,0x00B9B6,0x00DDDA,0x05FFFF,0x29FFFF,0x4EFFFF,0x003C6A,0x00608E,0x0085B3,0x00A9D7,0x00CEFB,0x17F2FF,0x3BFFFF,0x5FFFFF,0x002A87,0x004FAB,0x0073D0,0x0097F4,0x0ABCFF,0x2EE0FF,0x53FFFF,0x77FFFF,0x00179F,0x003BC3,0x0060E7,0x0384FF,0x27A8FF,0x4BCDFF,0x70F1FF,0x94FFFF,0x0002B0,0x0027D5,0x004BF9,0x2470FF,0x4894FF,0x6CB9FF,0x91DDFF,0xB5FFFF,0x0000BB,0x0013E0,0x2337FF,0x475BFF,0x6C80FF,0x90A4FF,0xB5C9FF,0xD9EDFF];
// swap palette RGB to BGR
for (var i=0; i<256; i++) {
var x = ASTROCADE_PALETTE[i];
x = ((x&0xff)<<16) | ((x>>16)&0xff) | (x&0x00ff00);
ASTROCADE_PALETTE[i] = x | 0xff000000;
}

View File

@ -45,8 +45,8 @@ function newPOKEYAudio() {
var pokey1 = new POKEYDeviceChannel();
var pokey2 = new POKEYDeviceChannel();
var audio = new MasterAudio();
audio.pokey1 = pokey1;
audio.pokey2 = pokey2;
audio['pokey1'] = pokey1; // TODO: cheezy
audio['pokey2'] = pokey2;
audio.master.addChannel(pokey1);
audio.master.addChannel(pokey2);
return audio;

View File

@ -56,7 +56,7 @@ export class CodeProject {
parseIncludeDependencies(text:string):string[] {
var files = [];
if (this.platform_id == 'verilog') {
var re = /^\s*(`include|[.]include)\s+"(.+?)"/gm;
var re = /^\s*(`include|[.]include)\s+"(.+?)"/gmi;
var m;
while (m = re.exec(text)) {
files.push('local/'+m[2]);
@ -65,7 +65,7 @@ export class CodeProject {
} else {
// for .asm -- [.]include "file"
// for .c -- #include "file"
var re2 = /^\s+([.#]?include)\s+"(.+?)"/gm;
var re2 = /^\s+([.#]?include)\s+"(.+?)"/gmi;
while (m = re2.exec(text)) {
files.push('local/'+m[2]);
files.push(m[2]);