home *** CD-ROM | disk | FTP | other *** search
- ;OrzEd-IC now uses the consolidated ACZ includes available with AsmStudio 3.1 or from the ACZ
- ; homepage at http://acz.calc.org/
- #include "ram86.h"
- #include "rom86.h"
- #include "asm86.h"
-
- #define lTable1 progEnd
- #define lTable2 progEnd + $20
- #define lTable3 progEnd + $40
- #define dataEnd progEnd + $60
-
- curLevelChar = $E748
- curLevel = $E749
- saveStack = $E74B
- dataStorage = $E74D
-
- .org _asm_exec_ram
- nop ;Mark program as AShell 1.1 compatable.
- jp AsmStart ;Jump to program init routine.
- .dw 0 ;Table version 0.
- .dw strDesc ;Pointer to description string.
-
- mDown:
- ld a, 7 ;7 is the lowest row.
- cp ixh
- jr z, main ;If we're already there, return.
- call flipCursor ;Remove old cursor.
- inc ixh ;Move down.
- call flipCursor ;Put new cursor.
- jr main
-
- mUp:
- xor a ;0 is the highest row.
- cp ixh
- jr z, main ;If we're already there, return.
- call flipCursor ;Remove old cursor.
- dec ixh ;Move up.
- call flipCursor ;Put new cursor.
- jr main
-
- mLeft:
- xor a ;0 is the leftmost column.
- cp ixl
- jr z, main ;If we're already there, return.
- call flipCursor ;Remove old cursor.
- dec ixl ;Move left.
- call flipCursor ;Put new cursor.
- jr main
-
- goThree:
- ld a, '3' ;For display.
- ld de, lTable3 ;Get the address of the third level.
- jr goNum
- goTwo:
- ld a, '2' ;For display.
- ld de, lTable2 ;Get the address of the second level.
- jr goNum
- goOne:
- ld a, '1' ;For display.
- ld de, lTable1 ;Get the address of the first level.
- goNum:
- ld (curLevelChar), a ;This is read to get level display character.
- ld (curLevel), de ;Write it to the current level address.
- jr preMain ;Redisplay screen before continuing.
-
- AsmStart:
- call _runindicoff
- nL_Restart:
- call _clrScrn
- ld ix, 0 ;ix is our r, c counter.
- ld a, '1' ;This is just the easiest way of keeping track of
- ld (curLevelChar), a ; the current level number.
- ld hl, lTable1
- ld (curLevel), hl ;We display Level One first.
- ld de, lTable1 + 1
- ld bc, $5F
- ld (hl), 0 ;Initialize first byte to zero.
- ldir
- preMain:
- call reDispScreen ;Redraws the entire display.
- main:
- call _get_key
- dec a ;Move cursor down.
- jr z, mDown
- dec a ;Move cursor left.
- jr z, mLeft
- dec a ;Move cursor right.
- jr z, mRight
- dec a ;Move cursor up.
- jr z, mUp
- cp K_SECOND - 4 ;If 2nd was pressed, draw a normal block.
- jr z, setBlockPrep1
- cp K_EXIT - 4 ;If exit was pressed, draw a tough block.
- jr z, setBlockPrep1
- cp K_MORE - 4 ;If more was pressed, draw a solid block.
- jr z, setBlockPrep1
- cp K_ALPHA - 4 ;If alpha was pressed, clear a block.
- jr z, setBlockPrep2
- cp K_1 - 4 ;Load the first level.
- jr z, goOne
- cp K_2 - 4 ;Load the second level.
- jr z, goTwo
- cp K_3 - 4 ;Load the third level.
- jr z, goThree
- cp K_F1 - 4 ;Clear all levels and reset name.
- jr z, newLevel
- cp K_F2 - 4 ;Load a level set.
- jp z, loadLevel
- cp K_F3 - 4 ;Save the current level set.
- jp z, saveLevel
- cp K_F4 - 4 ;Test the cirrent level set.
- jp z, testLevel
- cp K_F5 - 4 ;If F5 was pressed, just exit.
- jr nz, main
- doExit:
- ld a, $E1 ;Used to clear shiftflags 3-6.
- and (iy+shiftflags)
- ld (iy + shiftflags), a
- jp _clrScrn ;Clear screen before returning to shell.
-
- newLevel:
- ld hl, strUntitled ;Reset the name back to 'Untitled'
- ld de, strName + 2
- ld bc, $0008
- ldir
- ex de, hl
- inc hl
- ld (hl), $08 ;Reset the name length, too.
- jr nL_Restart ;See above, right after AsmStart.
-
- mRight:
- ld a, $0F ;F is the rightmost column.
- cp ixl
- jr z, main ;If we're already there, return.
- call flipCursor ;Remove old cursor.
- inc ixl ;Move right.
- call flipCursor ;Put new cursor.
- jr main
-
- setBlockPrep1:
- sub $05 ;$32, $33, $34 -> $2D, $2E, $2F
- setBlockPrep2:
- sub $2C ;$2C, $2D, $2E, $2F -> $00, $01, $02, $03
- setBlock:
- push ix ;Copy the r, c code into hl.
- pop hl
- push af ;Save block type.
- inc h ;This prevents the djnz from looping if h = 0.
- ld a, -5 ;Trust me, this makes the code simpler. <-----------------------+
- ld c, $04 ;Number of bytes in a row. |
- ld b, h ;Loop count = # of rows. |
- sB_Row: ; |
- add a, c ;See? This gets executed once even if h=0, so subtract 4 from --+
- djnz sB_Row ;If we still have rows to go, loop. |
- ld c, a ;We'll need a for the 'sub l' coming up. |
- ld a, l ;We need to subtract _from_ l. |
- ld l, $04 ;Four blocks in a byte. |
- sB_Col: ; |
- inc c ;And this gets executed once if l=0, so subtract one from -------+
- sub l
- jr nc, sB_Col ;If we still have bytes to go, loop.
- ld b, 0 ;Tricky way to ld bc, c.
- ld hl, (curLevel) ;Get the level offset.
- add hl, bc ;hl = current byte.
- pop bc ;Restore block type.
- push bc ;And save it again.
- inc a ;If it's the 4th block,
- jr z, sB_10 ; operate on bits 1 and 0.
- inc a ;If it's the 3rd block,
- jr z, sB_32 ; operate on bits 3 and 2.
- inc a ;If it's the 2nd block,
- jr z, sB_54 ; operate on bits 5 and 4.
- ld a, %00111111 ;Clear bits 7 and 6 (it's the first block).
- and (hl)
- rrc b ;Prepare b.
- rrc b
- jr sB_Done ;To Be Continued...
- sB_54:
- ld a, %11001111 ;Clear bits 5 and 4.
- and (hl)
- rrc b ;Prepare b.
- rrc b
- rrc b
- rrc b
- jr sB_Done
- sB_32:
- ld a, %11110011 ;Clear bits 3 and 2.
- and (hl)
- rlc b ;Prepare b.
- rlc b
- jr sB_Done
- sB_10:
- ld a, %11111100 ;Clear bits 1 and 0.
- and (hl)
- sB_Done:
- or b ;Plug the new type into a
- ld (hl), a ;Put the byte back.
- pop af ;Restore block type.
- call drawBlock ;redraw the block.
- ld hl, main
- push hl ;For flipCursor fallthrough.
-
- flipCursor:
- call getOffset ;Get screen offset of block ixh, ixl.
- ld de, $0010 ;One full line on the screen.
- add hl, de ;Skip the first line.
- ld a, $18 ;$18 = %00011000, the cursor half.
- xor (hl) ;Flip bits 3 & 4 in the screen byte.
- ld (hl), a ;Plug it back in.
- add hl, de
- ld a, $18
- xor (hl)
- ld (hl), a
- ret
-
- reDispScreen:
- push ix
- ld ix, 0 ;Start at the first brick.
- ld de, (curLevel) ;Load the memory offset of the current level.
- ld b, $20 ;We need to process 32 bytes.
- rDS_byte:
- push bc ;Save the byte count.
- ld b, 4 ;Four blocks per byte.
- ld a, (de) ;Get the current byte.
- ld c, a
- rDS_block:
- rlc c ;Bits 7 and 6 to 1 and 0.
- rlc c
- ld a, c
- and $03 ;Ignore bits 2-7.
- push de ;Can't lose this!
- call drawBlock ;Draw whatever type of block bits 1 and 0 represent.
- pop de ;Restore data pointer.
- inc ixl ;Increment the column.
- ld a, $10 ;If we hit the end of a line,
- cp ixl
- jr nz, rDS_goBlock
- ld ixl, 0
- inc ixh ;Increment the row.
- rDS_goBlock:
- djnz rDS_block ;If we're not done with this byte, loop.
- inc de ;Next byte!
- pop bc ;Restore the byte count.
- djnz rDS_byte ;If we're not done with the level, loop.
- ld hl, $0004 ;Just below the level display.
- ld (_curRow), hl
- ld a, (curLevelChar) ;Get level number (stored as a char)
- call _putc
- ld hl, strName ;Current name of the level set.
- call _puts
- ld hl, $3906 ;Set up menu at bottom of screen.
- ld (_penCol), hl
- ld hl, strNew
- call _vputs ;Display in small font.
- ld hl, $391F
- ld (_penCol), hl
- ld hl, strLoad
- call _vputs
- ld hl, $3938
- ld (_penCol), hl
- ld hl, strSave
- call _vputs
- ld hl, $3951
- ld (_penCol), hl
- ld hl, strTest
- call _vputs
- ld hl, $396C
- ld (_penCol), hl
- ld hl, strExit
- call _vputs
- pop ix ;Restore cursor position.
- jp flipCursor
-
- testLevel:
- push ix
- ld (saveStack), sp ;_exec_assembly isn't stack-friendly?
- ld hl, dataArea ;Store OrzEd86's data far enough above _asm_exec_ram
- ld de, dataStorage ; that it won't be overwritten by Orzunoid's code.
- ld bc, dataEnd - dataArea
- ldir
- ld hl, lTable1 - 2 ;Current levels.
- ld de, $C012 ;Level storage in RAM.
- ld bc, $0062 ;# of bytes to copy (3 levels * $20 + 2)
- ldir
- ld hl, strOrzunoid - 1 ;Orzunoid VAT entry in _OP1 format.
- rst 20h
- rst 10h
- jr c, tL_NotFound ;Orzunoid isn't on the calc!
- call _exec_assembly ;Execute Orzunoid.
- ld hl, dataStorage ;Retrieve the entire data area of OrzEd86
- ld de, dataArea
- ld bc, dataEnd - dataArea
- ldir
- ld sp, (saveStack) ;_exec_assembly isn't stack-friendly?
- pop ix
- jp preMain
- tL_NotFound:
- pop ix
- ld de, strNotFound
- jp dispMsg
-
- saveLevel:
- call nameLevel ;Get name to save as.
- ld hl, strName ;Copy name w/o leading length into _OP1.
- rst 20h
- ld a, (intNameLen) ;Retrieve name length.
- ld (_OP1 + 1), a ;Add leading length byte (z80 is byte-reversed).
- rst 10h ;Check to see if it already exists.
- jr nc, sL_Exists ;If it does, generate an error.
- ld hl, $70 ;$60 data + $0E code + 2 asm header = $70.
- call _createprog ;Allocate program memory and create VAT entry.
- ld a, b ;Move bde -> ahl.
- ex de, hl
- call _load_ram_ahl ;Set RAM page and convert hl to ASIC.
- ld de, rawProg ;Copy program contents from _asm_exec_ram to
- ld bc, $70 ; the memory just allocated by _CREATEPROG.
- ex de, hl
- inc de ;Skip the size bytes.
- inc de
- ldir
- ld de, strGoodSave
- jr dispMsg
- sL_Exists:
- pop hl ;Restore stack.
- pop hl
- ld de, strExists ;Display error text.
- jr dispMsg
-
- loadLevel:
- call nameLevel ;Get name to load from.
- ld hl, strName ;Put level set title into _OP1
- rst 20h
- ld a, (intNameLen)
- ld (_OP1 + 1), a
- rst 10h ;Gets var info if it exists.
- jr c, lL_NoProg ;If it doesn't, generate an error.
- and $1F ;Mask out flags
- cp $12 ;Is it a program?
- jr nz, lL_NotValid ;If not, generate an error.
- ld a, b ;move bde -> ahl
- ex de, hl
- call _load_ram_ahl ;Load appropriate RAM page.
- push hl ;We'll need this in a minute.
- call $0033 ;ld hl, (hl)
- ld de, $0070 ;Check to make sure the file is the proper length.
- call _cphlde
- pop hl
- jr nz, lL_NotValid ;Oops! It's not the right length...
- ld de, $0010 ;Find the marker bytes.
- add hl, de
- push hl ;We _still_ need this.
- call $0033 ;ld hl, (hl)
- ld de, $4FD0 ;$4FD0 = Orzunoid Level signature.
- call _cphlde
- pop hl
- jr nz, lL_NotValid ;If the signature doesn't exist, generate an error.
- inc hl ;Otherwise, load the levels!
- inc hl
- ld de, lTable1
- ld bc, $60
- ldir
- jp preMain
- lL_NoProg:
- ld de, strNoProg
- jr dispMsg
- lL_NotValid:
- ld de, strNotValid
-
- dispMsg:
- ld hl, $0005 ;Display below name.
- ld (_curRow), hl
- ex de, hl ;The offset of the text to display must be in de.
- call _puts ;Messages must be null-terminated.
- call _pause ;Hang around until they press a key.
- ld hl, $FE80 ;$FE80 = video address of the sixth line.
- ld de, $FE81
- ld bc, $017F
- ld (hl), 0
- ldir
- jp preMain ;Just as a rule of thumb, rediplay the level.
-
- nameLevel:
- ld a, (iy + shiftflags) ;Get shiftflags.
- or $50 ;Set shiftAlpha and shiftALock.
- ld (iy + shiftflags), a ;Save shiftslags.
- call _cursorOn ;We want the cursor displayed during text entry.
- ld de, strName + 2 ;Where the characters will go.
- ld a, (intNameLen) ;But first, we need to add the current offset.
- ld l, a
- ld h, 0
- add hl, de
- push hl ;I think _getkey screws with de and hl...
- nL_Loop: ;Used to update the display.
- ld hl, $0304 ;First letter of the name display.
- ld (_curRow), hl
- ld a, $20
- ld b, 9
- nL_OverWrite:
- call _putc
- djnz nL_OverWrite
- ld hl, $0304 ;First letter of the name display.
- ld (_curRow), hl
- ld hl, strName + 2 ;(Re)display the current name.
- call _puts
- nL_GetKey:
- call _getkey ;Use _getkey so we get Alpha handled for us.
- cp kEnter ;If it's enter, try to use this filename.
- jr z, nL_Next
- cp kDel ;If it's delete, remove the last charater typed.
- jr z, nL_Back
- add a, $14 ;L0 (font code) - k0 (key code) = 14 hex.
- cp L0 ;If it's less than 0, it's a bad character.
- jr c, nL_GetKey
- cp L9 + 1 ;If it's not more than 9, it's a numeral.
- jr c, nL_PrePutKey
- add a, $5 ;LcapA - kCapA = $14 + $5
- cp LcapA ;If it's less that A, it's a bad character.
- jr c, nL_GetKey
- cp LcapZ + 1 ;If it's not more than Z, it's a capital letter.
- jr c, nL_PutKey
- add a, $6 ;Lz - kz = $14 + $5 + $6
- cp Lz + 1 ;If it's not more than z, it's a lower-case letter.
- jr nc, nL_GetKey ;Otherwise, it's a bad character.
- jr nL_PutKey
- nL_PrePutKey: ;Need to make sure this isn't the first character.
- ld c, a ;We'll need a.
- ld a, (intNameLen) ;Grab the name length.
- ld b, 0 ;The first character cannot be a number.
- cp b
- jr z, nL_GetKey ;Numbers can't be the first character of a filename.
- ld a, c
- nL_PutKey:
- ld c, a ;We'll need a.
- ld a, (intNameLen) ;Grab the name length.
- ld b, 8 ;Filenames can't exceed 8 characters.
- cp b
- jr z, nL_GetKey
- inc a ;Increase the character count.
- ld (intNameLen), a ;Store the name length.
- pop hl ;Retrieve memory counter.
- ld (hl), c ;Load the character into memory.
- inc hl ;Increment the memory counter.
- push hl ;Store memory counter.
- jr nL_Loop ;Redisplay.
- nL_Back:
- ld a, (intNameLen) ;Grab the name length.
- ld b, 0 ;Can't backspace if it's there aren't any characters!
- cp b
- jr z, nL_GetKey
- dec a ;Decrease the character count.
- ld (intNameLen), a ;Store the name length.
- pop hl
- dec hl ;Decrement the memory counter.
- ld (hl), b ;Zero out the last character.
- push hl
- jr nL_Loop ;Redisplay
- nL_Next:
- ld a, (intNameLen) ;Grab the name length.
- ld b, 0 ;Can't use a zero-length name.
- cp b
- jr z, nL_GetKey
- call _cursorOff ;Get rid of cursor.
- pop hl
- ld (intNameLen), a ;Store the name length.
- ret
-
- drawBlock:
- call getOffset ;Change hl into screen offset.
- ld de, $0010 ;One full line on the screen.
- or a ;Is a 0?
- jr z, drawClear ;If so, clear the block.
- ld (hl), %11111111 ;All others start with $FF
- add hl, de
- dec a ;Was a 1?
- jr z, drawNorm ;If so, draw a normal block.
- dec a ;Was a 2?
- jr z, drawTough ;If so, draw a tough block.
- ld a, %11111111 ;Else, it's solid.
- ld (hl), a
- add hl, de ;Move down one line.
- ld (hl), a
- add hl, de
- ld (hl), a
- ret
- drawTough:
- ld (hl), %11000011 ;Second line of sprite.
- add hl, de
- ld (hl), %11000011 ;Third line of sprite.
- add hl, de
- ld (hl), %11111111 ;Last line of sprite.
- ret
- drawNorm:
- ld (hl), %10000001
- add hl, de
- ld (hl), %10000001
- add hl, de
- ld (hl), %11111111
- ret
- drawClear:
- ld (hl), a ;a is already 0.
- add hl, de
- ld (hl), a
- add hl, de
- ld (hl), a
- add hl, de
- ld (hl), a
- ret
-
- getOffset:
- push ix ;Copy ix into de.
- pop de
- ld l, d ;Change ixh into a 16-bit value in hl.
- ld h, 0
- ld d, $FC ;Load d with the upper byte of the screen offset.
- add hl, hl ;hl = Row * 64
- add hl, hl
- add hl, hl
- add hl, hl
- add hl, hl
- add hl, hl
- add hl, de ;hl = Screen Offset + Row * 64 + Column
- ret
-
- dataArea:
- strDesc:
- .db "Orzunoid Level Editor v.8b", 0
- strExists:
- .db "File already exists!", 0
- strGoodSave:
- .db "Level set saved.", 0
- strName:
- .db ": Untitled", 0
- intNameLen:
- .db 8
- strNoProg:
- .db "No such file exists!", 0
- strNotFound:
- .db "Orzunoid not found!", 0
- strNotValid:
- .db "Not a level set!", 0
- strOrzunoid:
- .db 8, "Orzunoid"
- strUntitled:
- .db "Untitled"
- strNew:
- .db "New", 0
- strLoad:
- .db "Load", 0
- strSave:
- .db "Save", 0
- strTest:
- .db "Test", 0
- strExit:
- .db "Exit", 0
- rawProg:
- .db $8E, $28 ;Assembly program ID bytes (TI)
- ld de, $C012 ;Level storage in RAM.
- ld hl, $D754 ;_asm_exec_ram + $0C
- ld bc, $0062 ;# of bytes to copy (3 levels * $20 + 2)
- ldir
- ret
- .db $D0, $4F ;These tell Orzunoid that this is a valid level set.
-
- progEnd:
- .end
-