Quiero saber si este juego en asm se puede ejecutar en Visual studio bajo C++ nativo, ya que ejecutas asm también. Lo que no se hacerlo ya que no hago pruebas desde hace añazos.
¿Es posible ejecutarlo?
Código ASM.
Código
cXLimIzq EQU 32 ; X-Limite izquierda juego cXLimDer EQU 320-cXLimIzq ; X-Limite derecha juego cYLimSup EQU 60 ; Y-Limite superior juego cYLimInf EQU 180 ; Y-Limite inferior juego cIncYEDisp EQU 1 ; Y-incremento de los e-disparos cTamDefFig EQU 7*2 ; Los words que definen la figura cSepIniEDisp EQU 4 ; Separación inicial del disparo enemigo cColorEDisp EQU 14 ; Color del disparo enemigo cColorPDisp EQU 7 ; Color del disparo del jugador cFigAlto EQU 7 ; Altura de las figuras cFigAncho EQU 16 ; Anchura de las figuras cAncho EQU 256 ; Anchura de la pantalla de juego cAlto EQU cYLimInf-cYLimSup+1 ; Altura de la pantalla de juego cSepMargen EQU 3 ; Margen de separación con el borde cLinColor EQU 6 ; Color de la línea contenedora cFrecBomb EQU 010h ; Frecuencia con la que empiezan a caer bombas cNumEColumn EQU 11 ; Número de columnas de enemigos cNumEnemigos EQU 5*cNumEColumn ; Número de enemigos cDispEne EQU 5 ; Máximo num disparos x cada enemigo cNumDispEne EQU 7;cDispEne*cNumEColumn; Máximo disparos activos enemigos cXESep EQU 1 ; X-separación entre enemigos cYESep EQU 3 ; Y-separación entre enemigos cXESup EQU (cAncho-((16+cXESep)*10+16))/2 ; X-inicial-superior enemigos cYESup EQU cYLimSup-cYLimSup ; Y-superior enemigos cYPSup EQU cYLimInf-7-cYLimSup ; Y-superior player cXPIzq EQU 0 ; X-lim izquierda player cXPDcha EQU 256-11 ; X-lim derecha player cTimePlayer EQU 0 ; Tiempo retardo movimiento player cTimeEnemigos EQU 20 ; Tiempo retardo movimiento enemigos cTimePDisp EQU 0 ; Tiempo retardo movimiento player-disparo cTimeEDisp EQU 0 ; Tiempo retardo movimiento enemigos-disparos cTimeESgteDisp EQU 10 ; Tiempo retardo siguiente enemigos-disparos cChgTEnemigos EQU 2 ; Cada cuántos enemigos destruidos incrementan velocidad cFilasBaja EQU 2 ; Filas que bajan los enemigos cada vez cYTope EQU cYPSup-10 ; Tope superior que no pueden sobrepasar enemigos cSoyInmune EQU 0 ; 1-soy inmune, 0-no soy inmune cTAMTOT EQU 1024*6 ; Este programa y su pila caben en 6Kb cnNotas EQU 7+6+7+5 TEnemigos STRUC PosX DW ? PosY DW ? OldPosX DW ? Def DW ? ; La dirección donde está definido Despl DW ? ; El desplazamiento de offsets (+7?) Tipo DB ? ; 1, 2, 3, 4, 5 Color DB ? Vida DB ? Abajo DB ? ; Sólo disparan los que estén abajo TEnemigos ENDS TCabEDisp STRUC ; Estructura de la cabecera de los disparos enemigos DirDisp DW ? ; Dirección donde se encuentra el disparo Vida DB ? ; ¿Está vivo? TCabEDisp ENDS TEDisparos STRUC ; Disparos de los enemigos PosX DW ? PosY DW ? Def DW ? ; Matriz de definición del disparo Despl DW ? ; junto con el desplazamiento de offsets (+7?) Color DB ? TEDisparos ENDS TPlayer STRUC PosX DW ? PosY DW ? Def DW ? ; La dirección donde está definido Color DB ? Vida DB ? TPlayer ENDS TPDisparos STRUC ; Disparos del jugador PosX DW ? PosY DW ? Def DW ? Despl DW ? ; El desplazamiento de offsets (+7?) Color DB ? Vida DB ? TPDisparos ENDS TNota STRUC Frecuencia DW ? Duracion DB ? TNota ENDS LTEnemigos EQU SIZEOF TEnemigos LTEDisparos EQU SIZEOF TEDisparos LTCabEDisp EQU SIZEOF TCabEDisp LTPlayer EQU SIZEOF TPlayer LTPDisparos EQU SIZEOF TPDisparos LTNota EQU SIZEOF TNota IF1 INCLUDE ..\LIB\CtesGphM.inc ; Constantes gráficas INCLUDE ..\LIB\GraphMM.inc ; Incorporamos las macros gráficas ENDIF codigo SEGMENT PARA PUBLIC 'CODE' ; Abre el segmento de código ASSUME CS:codigo, DS:codigo, ES:codigo, SS:codigo ORG 100h ; COM -> comienza en 100h Entrada PROC ; Abre el procedimiento ; *** Reasigna memoria MOV SP, cTAMTOT ; La base de la pila MOV AH, 4Ah MOV BX, cTAMTOT/16 ; Lo pasamos a párrafos INT 21h ; Redimensionamos el bloque de memoria JNC $_Bien1 MOV AH, 9 MOV DX, OFFSET msg1 INT 21h JMP $_Salimos $_Bien1: CALL VGAColor ; Comprobamos si existe VGA en color ; Reserva memoria para el búfer pant1 MOV BX, (cXLimDer-cXLimIzq+1)*(cYLimInf-cYLimSup+1)/16+1 ; En párrafos CALL ResMem MOV WORD PTR [ScrSeg], AX SetMode 13h ; Ponemos el modo gráfico CALL DibMarco CALL SaveValSPK CALL Randomize CALL SaveOldInt9h CALL SetNewInt9h CALL SaveOldInt1Ch CALL SetNewInt1Ch CALL IniCabEDisp CALL ResetNivel ; Inicializamos el nivel del juego $_Nueva_Partida: CALL IniElementos ; Inicializa valores en función de variables y constantes $_Main: CALL GetPShoot ; ¿Hemos pulsado ctrl? CALL GetEShoot ; ¿Debe disparar un enemigo? CALL SetMotion ; Movemos las piezas si toca JNC $_Next0 ; Si STC = 1 significa que los enemigos han llegado al nivel inferior: ganaron CALL ResetNivel ; Inicializamos el nivel del juego CALL WaitUntilCtrl ; Esperamos hasta Ctrl pulsado JMP $_Nueva_Partida $_Next0: CMP BYTE PTR [NumEnemigos], 0 JA $_Next1 CALL incNivel ; Incrementamos el nivel del juego JMP $_Nueva_Partida $_Next1: CMP BYTE PTR [Player.Vida], 0 JA $_Next2 CALL ResetNivel ; Inicializamos el nivel del juego CALL WaitUntilCtrl ; Esperamos hasta Ctrl pulsado JMP $_Nueva_Partida $_Next2: CALL ClearBuffer ; Limpiamos el búfer CALL DibujaEnemigos ; Dibujamos los enemigos en el búfer CALL DibujaJugador ; Dibujamos el jugador en el búfer CALL DibujaPDisparo ; Dibujamos el disparo del jugador en búfer CALL DibujaEDisparo ; Dibujamos los disparos de los enemigos en búfer CALL CheckPDEDColision ; ¿El disparo del jugador alcanzo al de algun enemigo? CALL CheckMPDColision ; ¿El disparo del jugador alcanzo algun enemigo? CALL CheckMEDColision ; ¿El disparo de los enemigos alcanzaron al jugador? WRetrace 8 ; Esperamos al final del retrazo MOV AX, WORD PTR [ScrSeg] ; Segmento Origen MOV BX, __VgaSeg ; Segmento destino: mem vídeo CALL Copy64K ; Vuelca búfer en mem vídeo CMP BYTE PTR [Escape], 1 JNZ $_Main SetMode 3h ; Volvemos al modo texto CALL RestoreOldInt1Ch CALL RestoreOldInt9h CALL TurnOffSpk MOV AX, WORD PTR [ScrSeg] ; Libera memoria pantalla CALL LibMem $_Salimos: ; Salimos al DOS MOV AX, 4C00h ; Servicio 4Ch, mensaje 0 INT 21h ; volvemos AL DOS Entrada ENDP ; cierra el procedimiento IF1 INCLUDE ..\LIB\VGA_M.inc ; Incorporamos procedimientos INCLUDE ..\LIB\SpcM.inc ; Incorporamos procedimientos ENDIF ; **************** TurnOffSpk PROC ; Propósito: Apaga el altavoz ; Entrada : Ninguna ; Salida : Ninguna ; Destruye : AX MOV AL, BYTE PTR [vbSpeaker] AND AL, 11111100b ; Apagamos y descconectamos el altavoz del canal 2 del PIT OUT 61h, AL RET TurnOffSpk ENDP SaveValSPK PROC ; Propósito: Guarda el valor original del puerto 61h ; Entrada : Ninguna ; Salida : Ninguna ; Destruye : AX IN AL, 61h AND AL, 11111100b MOV BYTE PTR [vbSpeaker], AL RET SaveValSPK ENDP Frec_Periodo PROC ; Propósito: Convertimos la frecuencia en período ; Entrada : CX: frecuencia ; Salida : DX: período ; Destruye : AX, DX MOV DX, 12h MOV AX, 34DCh DIV CX MOV DX, AX ; Lo guardamos en DX RET Frec_Periodo ENDP PIT_REG_COMM PROC ; Propósito: Le indicamos al PIT lo que vamos a hacer ; Entrada : DX:periodo ; Salida : Ninguna ; Destruye : AX MOV AL, 0B6h OUT 43h, AL MOV AL, DL ; Pasamos el byte bajo del contador OUT 42h, AL MOV AL, DH ; Y ahora el alto OUT 42h, AL RET PIT_REG_COMM ENDP SpkOn PROC ; Propósito: Encendemos el altavoz con duración determinada ; Entrada : Ninguna ; Salida : Ninguna ; Destruye : AX MOV AL, BYTE PTR CS:[vbSpeaker] OR AL, 3 OUT 61h, AL RET SpkOn ENDP SpkOff PROC ; Propósito: Encendemos el altavoz con duración determinada ; Entrada : Ninguna ; Salida : Ninguna ; Destruye : AX MOV AL, BYTE PTR CS:[vbSpeaker] AND AL, 11111100b OUT 61h, AL RET SpkOff ENDP Sonido PROC ; Propósito: Toca una nota en el altavoz del PC a través del PIT ; Entrada : CX:frecuencia ; Salida : Ninguna ; Destruye : Ninguna .IF CX == 0 CALL SpkOff .ELSE CALL Frec_Periodo CALL PIT_REG_COMM CALL SpkOn .ENDIF RET Sonido ENDP ResetNota PROC ; Propósito: Recogemos los valores de la nueva nota en MNota ; entrada : KeyTable ; salida : KeyTable ; Destruye : AX PUSH AX PUSH BX MOV BX, WORD PTR CS:[vwActual] MOV AX, WORD PTR CS:[Notas1+BX] MOV WORD PTR CS:[MNota.Frecuencia], AX MOV AX, WORD PTR CS:[Notas1+BX+2] MOV BYTE PTR CS:[MNota.Duracion], AL POP BX POP AX RET ResetNota ENDP ; **************** SaveOldInt1Ch PROC NEAR ; Propósito: Guarda la dirección de la antigua ISR de Int 1Ch ; entrada : OldInt1Ch ; salida : Ninguna ; Destruye : AX MOV AX, 351Ch ; Obtiene la dirección de la INT 21h ; interrupción 1Ch MOV WORD PTR OldInt1Ch[2],ES ; Guarda segmento MOV WORD PTR OldInt1Ch[0],BX ; y dirección RET SaveOldInt1Ch ENDP RestoreOldInt1Ch PROC NEAR ; Propósito: Restaura la dirección de la antigua ISR de Int 1Ch ; entrada : OldInt1Ch ; salida : Ninguna ; Destruye : AX, DX PUSH DS ; Guardamos DS LDS DX, OldInt1Ch ; Carga la dirección original MOV AX, 251Ch ; Lo restaura a la tabla de vectores INT 21h POP DS RET RestoreOldInt1Ch ENDP SetNewInt1Ch PROC NEAR ; Propósito: Establece la dirección de la nueva ISR para Int 1Ch ; entrada : NuevaInt1Ch ; salida : Ninguna ; Destruye : AX, DX MOV DX, OFFSET NuevaInt1Ch ; Carga la dirección de nueva rutina MOV AX, 251Ch ; Establece la nueva interrupción INT 21h RET SetNewInt1Ch ENDP NuevaInt1Ch PROC FAR ; Propósito: Nueva ISR para la INT 1Ch, crea un retardo ; entrada : Ninguna ; salida : Ninguna ; Destruye : Ninguna PUSHF PUSH AX PUSH BX PUSH CX PUSH DX PUSH DS PUSH ES .IF BYTE PTR CS:[vbEjecutando] == 1 ; Si está sonando la nota DEC BYTE PTR CS:[MNota.Duracion] ; Decrementamos la duración .IF BYTE PTR CS:[MNota.Duracion] == 0 ; Si ya ha terminado la duración de la nota ADD WORD PTR CS:[vwActual], 4 ; Incrementamos puntero a notas CALL ResetNota ; Recogemos nueva nota .IF WORD PTR CS:[vwActual] >= cnNotas*4 ; Si ya hemos terminado todas las notas MOV BYTE PTR CS:[vbEjecutando], 0 ; Marcamos que no tocamos MOV WORD PTR CS:[vwActual], 0 ; Reseteamos el puntero a notas CALL TurnOffSpk .ELSE ; Si todavía no hemos terminado todas las notas MOV CX, WORD PTR CS:[MNota.Frecuencia] CALL Sonido .ENDIF .ENDIF .ELSE ; Si no está sonando ninguna nota .IF BYTE PTR CS:[vbEjecutar] == 1 ; Si debemos ejecutar las notas .IF WORD PTR CS:[vwActual] == 0 ; Si estamos al inicio, reseteamos CALL ResetNota .ENDIF .IF BYTE PTR CS:[MNota.Duracion] != 0 ; Si todavía dura la nota, la tocamos MOV BYTE PTR CS:[vbEjecutando], 1 ; Marcamos para tocar MOV CX, WORD PTR CS:[MNota.Frecuencia] CALL Sonido .ENDIF .ENDIF .ENDIF CMP BYTE PTR CS:[TimePlayer], 0 JZ $_Next1 DEC BYTE PTR CS:[TimePlayer] ; Decrementamos el contador de pulsos $_Next1: CMP BYTE PTR CS:[TimeEnemigos], 0 JZ $_Next2 DEC BYTE PTR CS:[TimeEnemigos] ; Decrementamos el contador de pulsos $_Next2: CMP BYTE PTR CS:[TimePDisp], 0 JZ $_Next3 DEC BYTE PTR CS:[TimePDisp] ; Decrementamos el contador de pulsos $_Next3: CMP BYTE PTR CS:[TimeEDisp], 0 JZ $_Next4 DEC BYTE PTR CS:[TimeEDisp] ; Decrementamos el contador de pulsos $_Next4: CMP BYTE PTR CS:[TimeESgteDisp], 0 JZ $_GT_Next5 DEC BYTE PTR CS:[TimeESgteDisp] ; Retardo para el siguiente disparo de los enemigos $_GT_Next5: POP ES POP DS POP DX POP CX POP BX POP AX POPF JMP [CS:OldInt1Ch] ; Saltamos a la vieja rutina NuevaInt1Ch ENDP TopInvader1 DW 0c00h,1e00h,2d00h,3f00h,1200h,2100h,1200h ; 0c00 0000110000000000 ; 1e00 0001111000000000 ; 2d00 0010110100000000 ; 3f00 0011111100000000 ; 1200 0001001000000000 ; 2100 0010000100000000 ; 1200 0001001000000000 TopInvader2 DW 0c00h,1e00h,2d00h,3f00h,1200h,2100h,4080h ; 0c00 0000110000000000 ; 1e00 0001111000000000 ; 2d00 0010110100000000 ; 3f00 0011111100000000 ; 1200 0001001000000000 ; 2100 0010000100000000 ; 4080 0100000010000000 MiddleInvader1 DW 2100h,9e40h,0ad40h,7f80h,3f00h,2100h,4080h MiddleInvader2 DW 2100h,1e00h,2d00h,7f80h,0bf40h,0a140h,1200h BottomInvader1 DW 01e00h,7f80h,0ccc0h,0ffc0h,2100h,4c80h,2100h BottomInvader2 DW 01e00h,7f80h,0ccc0h,0ffc0h,2100h,4c80h,8040h PlayersShip DW 0400h,0e00h,7fc0h,0ffe0h,0ffe0h,0ffe0h,0000h ; 0400 0000010000000000 ; 0e00 0000111000000000 ; 7fc0 0111111111000000 ; ffe0 1111111111100000 ; ffe0 1111111111100000 ; ffe0 1111111111100000 ; 0000 0000000000000000 TwistedMissile1 DW 0000h,0000h,0000h,0800h,0400h,0800h,0400h ; 0000 0000000000000000 ; 0000 0000000000000000 ; 0000 0000000000000000 ; 0800 0000100000000000 ; 0400 0000010000000000 ; 0800 0000100000000000 ; 0400 0000010000000000 TwistedMissile2 DW 0000h,0000h,0000h,0400h,0800h,0400h,0800h StraightMissile DW 0000h,0000h,0000h,0400h,0400h,0400h,0400h MEnemigos TEnemigos cNumEnemigos DUP (<>) ; Enemigos sin inicializar MCabEDisp TCabEDisp cNumDispEne DUP (<>) ; Disparos de los enemigos ; align 16 ; db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 ;16 MEDisparos TEDisparos cNumDispEne DUP (<>) ; Disparos de los enemigos Player TPlayer <> ; Jugador sin inicializar MPDisparos TPDisparos <> ; Disparos de los enemigos vbSpeaker DB ? vbEjecutar DB 1 ; Lo definimos indicando que suenen las notas vbEjecutando DB 0 vwActual DW 0 Notas1 DW 262, 3, 330, 3, 349, 3, 392, 3, 349, 3, 294, 3, 0, 8 ; 7 DW 262, 3, 330, 3, 349, 3, 392, 3, 349, 3, 0, 8 ; 6 DW 262, 3, 330, 3, 349, 3, 392, 3, 349, 3, 294, 3, 0, 8 ; 7 DW 330, 3, 349, 3, 330, 3, 262, 3, 262, 3 ; 5 MNota TNota <> msg1 DB "Error al REDIMENSIONAR memoria$" msg2 DB "Error al RESERVAR memoria$" msg3 DB "Error al LIBERAR memoria$" msgAOE DB "(c)Abre los ojos al ensamblador", 13, 10 DB "Ejemplo de space invaders$" msgExito DB "Enhorabuena, has salvado al planeta Tierra$" msgFracaso DB "Por tu impericia la Tierra ha sido destruida$" msgBlanco DB " $" NumEnemigos DB ? ; Número de enemigos que quedan OldInt9h DD ? ; Dirección antigua de Int 9h OldInt1Ch DD ? ; Dirección antigua de Int 1Ch ScrSeg DW ? ; Segmento del búfer de pantalla DirEnemigos DW ? ; Dirección del mvto de los enemigos DesplDefFig DW ? ; Para pintar el mvto de la figura TimePlayer DB ? ; Retardo para el mvto del jugador TimeEnemigos DB ? ; Retardo para el mvto de los enemigos TimePDisp DB ? ; Retardo para el mvto disparo jugador TimeEDisp DB ? ; Retardo para el mvto disparo enemigos TimeESgteDisp DB ? ; Retardo para el siguiente disparo enemigos vNextTEnemigos DB ? ; Siguiente retardo de los enemigos TicksReloj DD ? ; Ticks de reloj ActFrecBomb DB ? ; Frecuencia actual disparos enemigos (cambia) NumEColumn DW ? ; Número de columnas de enemigos que quedan ChgTEnemigos DB ? ; Cada cuantos enemigos muertos incr su velocidad vSoyInmune DB cSoyInmune ; Ser o no ser inmune ; Datos modificados en cada nivel vYESup DW ? ; X-inicial-superior de los enemigos ; Datos que modifica la nueva ISR del teclado PlayerLeft DB 0 PlayerRight DB 0 PlayerFire DB 0 Escape DB 0 codigo ENDS END Entrada
Más códigos aquí.
http://abreojosensamblador.epizy.com/?Tarea=1&SubTarea=35&i=1
Gracias.